Typical POSIX thread implementations do not perform any checks or validations that the thread unlocking a mutex is the same as the one that locked that (or likely even that the mutex was locked in the first place). This is not how mutexes are supposed to be used. The word "mutex" means mutual exclusion; the purpose of the concept is to provide a mechanism for multiple threads to safely access or modify a resource (e.g. data structure) without other threads interfering, and when done a modification have the resource in consistent state before unlocking the mutex.
It could be nice to catch such programming errors in run time (just like catching out of bounds writes to arrays), but by default providing such book-keeping and guards are too expensive in terms of performance; mutex locking and unlocking operations are supposed to give you minimal overhead for them to be usable. This is the reason you are succeeding in unlocking your mutexes from a wrong thread. In standard Linux pthread implementation you could use "error checking" mutexes, which would give you error when you try to unlock a mutex from a wrong thread, but again this check exists only to catch programming errors.
I am not able to advice you in compact form about what to use for and how to implement your signaling without better understanding of the nature of your signaling need.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…