通常,如果task1持有锁A,则想要获取锁B而另一个任务2已经获取锁B并且正在等待由task1持有的锁A,这会导致死锁。
但是当涉及到pthread_mutex_timedlock时,它会在指定的超时后尝试互斥锁定或超时。
我遇到了僵局的情况,我试图采取定时锁定,这最终会超时,这让我很困惑。
编辑:通过更好的设计可以避免死锁,这是我最终做的,我确保采用互斥锁的顺序是相同的,以避免死锁 但是,由于我选择了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.
答案 0 :(得分:2)
在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 == EDEADLK
和kind
可能是PTHREAD_MUTEX_ERRORCHECK_NP
或PTHREAD_MUTEX_RECURSIVE_NP
。另一件需要注意的事情是在检查之前处理超时,即你没有达到超时。
在内核中,futex_lock_pi_atomic()
返回EDEADLK代码:
/*
* Detect deadlocks.
*/
if ((unlikely((curval & FUTEX_TID_MASK) == vpid)))
return -EDEADLK;
/*
上面的部分比较了锁定互斥锁的线程的TID和尝试获取互斥锁的线程的TID。如果它们是相同的,则表明该线程正在尝试获取它已经获取的互斥锁。
答案 1 :(得分:0)
首先,超时指定的时间是多少?它大吗?
pthread_mutex_timedlock在三个条件下失败 1 GT;检测到死锁条件或当前线程已拥有互斥锁。 2&gt;无法获取互斥锁,因为已超过互斥锁的最大递归锁定数。 3&gt; mutex指定的值不是指初始化的互斥对象。
您的代码是否受到上述任何操作。
此外,代码snipet可能有助于我们清楚地看到问题。