在多线程系统上,如果两个线程要在锁定互斥锁后要在共享内存上工作。
线程A:
pthread_mutex_lock(&mutex)
....... //Memory corruption or Assert and thread exits
pthread_mutex_unlock(&mutex)
线程B:
pthread_mutex_lock(&mutex)
.......
pthread_mutex_unlock(&mutex)
如果线程A首先获取互斥锁并由于内存损坏或断言而退出,则线程B将永远等待,从而导致死锁。
最佳答案
您可以在互斥锁上设置ROBUST
属性。使用健壮的互斥锁,如果获取该互斥锁的线程由于某种原因退出而没有将其解锁,则该互斥锁会进入特殊状态,下一个尝试锁定该互斥锁的线程将获得EOWNERDEAD
。
然后,该线程负责清理任何不一致的状态。如果可以恢复,则该线程应在pthread_mutex_consistent(3)
之前的任何时间调用pthread_mutex_unlock(3)
,以便其他线程可以像以前一样使用它。如果无法恢复,则互斥锁应该在不调用pthread_mutex_consistent(3)
的情况下被解锁,从而导致其进入无法使用的状态,其中唯一允许的操作是销毁它。
请注意,即使返回了EOWNERDEAD
,该互斥锁也会被锁定(我认为这是pthread_mutex_lock(3)
返回错误但锁定互斥锁的唯一条件)。
要设置ROBUST
属性,请在初始化互斥锁属性实例后使用pthread_mutexattr_setrobust(3)
。请记住,必须在初始化互斥锁之前完成此操作。因此,类似:
pthread_mutex_t mutex;
pthread_mutexattr_t mutex_attrs;
if (pthread_mutexattr_init(&mutex_attrs) != 0) {
/* Handle error... */
}
if (pthread_mutexattr_setrobust(&mutex_attrs, PTHREAD_MUTEX_ROBUST) != 0) {
/* Handle error... */
}
if (pthread_mutex_init(&mutex, &mutex_attrs) != 0) {
/* Handle error... */
}
然后,您可以像这样使用它:
int lock_res = pthread_mutex_lock(&mutex);
if (lock_res == EOWNERDEAD) {
/* Someone died before unlocking the mutex
* We assume there's no cleanup to do
*/
if (pthread_mutex_consistent(&mutex) != 0) {
/* Handle error... */
}
} else if (lock_res != 0) {
/* Some other error, handle it here */
}
/* mutex is locked here, do stuff... */
if (pthread_mutex_unlock(&mutex) != 0) {
/* Handle error */
}
有关更多信息,请参见pthread_mutex_consistent(3)和pthread_mutex_getrobust(3) / pthread_mutex_setrobust(3)的手册页。
关于linux - 如何摆脱Linux的僵局,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31638790/