lock了mutex的线程退出了却没有unlock时会怎么样?
解释当一个lock了mutex的线程退出了,却没有主动unlock这个mutex时,会发生什么
If you created a robust mutex by setting up the right attributes before calling pthread_mutex_init, the mutex will enter a special state when the thread that holds the lock terminates, and the next thread to attempt to acquire the mutex will obtain an error of EOWNERDEAD. It is then responsible for cleaning up whatever state the mutex protects and calling pthread_mutex_consistent to make the mutex usable again, or calling pthread_mutex_unlock (which will make the mutex permanently unusable; further attempts to use it will return ENOTRECOVERABLE).
假设在pthread_mutex_init的时候,通过设置合适的属性得到一个robust mutex,当一个拥有该mutex的线程exit,并且没有unlock这个mutex的时候,该mutex就会进入一个specail state。另外一个线程想要lock这个mutex的时候,会返回一个EOWNERDEAD错误。这个时候就需要清除该mutex的状态,有两个办法:
- 调用pthread_mutex_consistent可以使得改mutex再次usable
- pthread_mutex_unlock使得该mutex永久unusable,尝试再次使用该mutex的将会得到ENOTRECOVERABLE错误
For non-robust mutexes, the mutex is permanently unusable if the thread that locked it terminates without unlocking it. Per the standard (see the resolution to issue 755 on the Austin Group tracker), the mutex remains locked and its formal ownership continues to belong to the thread that exited, and any thread that attempts to lock it will deadlock. If another thread attempts to unlock it, that's normally undefined behavior, unless the mutex was created with the PTHREAD_MUTEX_ERRORCHECK attribute, in which case an error will be returned.
对non-robust mutexes,如果持有锁的线程退出且没有unlock该锁,那么该mutex将会永久不可以使用。这个mutex会保持被已经退出的该线程持有lock的状态,任何尝试lock这个mutex的线程将陷入deadlock状态。如果任何线程尝试unlock这个mutex,那么将会产生undefined behavior。但如果mutex创建的时候设置了PTHREAD_MUTEX_ERRORCHECK属性,那么unlock将会返回错误。
On the other hand, many (most?) real-world implementations don't actually follow the requirements of the standard. An attempt to lock or unlock the mutex from another thread might spuriously succeed, since the thread id (used to track ownership) might have been reused and may now refer to a different thread (possibly the one making the new lock/unlock request). At least glibc's NPTL is known to exhibit this behavior.
但是,很多real-world的实现版本却没有满足standard的要求。由于thread id可能会被重用,所以,有时候lock或者unlock会产生不合逻辑的成功,比如一个线程A lock了某个mutex,然后该A线程id给别的线程B用了,那么线程B去unlock也会成功。比如glibc's NPTL就会表现出这样的行为。