在多线程系统上,如果两个线程要在锁定互斥锁后要在共享内存上工作。

线程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/

    10-11 07:41