pthread_mutex_timedlock和死锁

通常情况下,如果task1持有锁A想要取得锁B,而另一个task2取得了锁B并且正在等待task1持有的锁A,则会导致死锁。

但是,当涉及到pthread_mutex_timedlock时,它会在指定的超时后尝试互斥锁或超时。

我打了一个僵局,在那里我试图采取定时锁,这将最终超时,这让我感到困惑。

编辑:通过更好的devise可以避免死锁,这是我最终做的,我确保了互斥锁的顺序是相同的,以避免死锁,但问题仍然是开放的,如果死锁是可以避免的我select了timedlock

有人能解释我这种行为吗?

编辑:附上一个示例代码,使场景更清晰(真正的任务相当复杂,并运行到数千行)

T1

pthread_mutex_lock(&lockA); //call some API, which results in a lock of m2 pthread_mutex_lock(&lockB); //unlock in the order pthread_mutex_unlock(&lockB); pthread_mutex_unlock(&lockA); 

T2

 pthread_mutex_lock(&lockB); //call some API, which results in locking m1 pthread_mutex_timedlock(&lockA,<10 sec>); 

崩溃是在T2的背景下看到的,bt:

 Program terminated with signal 6, Aborted. #0 0x57edada0 in raise () from /lib/libc.so.6 (gdb) bt #0 0x57edada0 in raise () from /lib/libc.so.6 #1 0x57edc307 in abort () from /lib/libc.so.6 #2 0x57ed4421 in __assert_fail () from /lib/libc.so.6 #3 0x57bb2a7c in pthread_mutex_timedlock () from /lib/libpthread.so.0 

我跟踪错误

 pthread_mutex_timedlock: Assertion `(-(e)) != 35 || (kind != PTHREAD_MUTEX_ERRORCHECK_NP && kind != PTHREAD_MUTEX_RECURSIVE_NP)' failed. 

在glibc源代码中, pthread_mutex_timedlock()这个断言看起来像这样:

  int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, __lll_private_flag (FUTEX_LOCK_PI, private), 1, abstime); if (INTERNAL_SYSCALL_ERROR_P (e, __err)) { if (INTERNAL_SYSCALL_ERRNO (e, __err) == ETIMEDOUT) return ETIMEDOUT; if (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH || INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK) { assert (INTERNAL_SYSCALL_ERRNO (e, __err) != EDEADLK || (kind != PTHREAD_MUTEX_ERRORCHECK_NP && kind != PTHREAD_MUTEX_RECURSIVE_NP)); /* ESRCH can happen only for non-robust PI mutexes where the owner of the lock died. */ assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH || !robust); 

这可能是e == EDEADLKkindPTHREAD_MUTEX_ERRORCHECK_NPPTHREAD_MUTEX_RECURSIVE_NP 。 另外要注意的是超时是在这个检查之前处理的,也就是说你没有超时。

在内核中,它是返回EDEADLK代码的futex_lock_pi_atomic()

  /* * Detect deadlocks. */ if ((unlikely((curval & FUTEX_TID_MASK) == vpid))) return -EDEADLK; /* 

上面的代码比较了已经锁定互斥锁的线程的TID和尝试获取互斥锁的线程的TID。 如果它们是相同的,则暗示该线程试图获取它已经获得的互斥体。

首先是什么时间规定的时间? 这是大吗?

pthread_mutex_timedlock在三种情况下失败1>检测到死锁情况,或者当前线程已经拥有该互斥锁。 2>互斥锁无法获取,因为超过了互斥量递归锁的最大数量。 3>互斥体指定的值不引用已初始化的互斥体对象。

是你的代码受到上述任何一个。

另外代码snipet可能有助于清除事情,我们看到的问题。