在我的程序中,我的死锁有问题。所以我一直在读关于锁的文章,但问题是大多数信息都是不一致的,或者没有定义平台。在Recursive Lock (Mutex) vs Non-Recursive Lock (Mutex),最被接受的答案是:
因为递归互斥具有所有权,所以获取互斥的线程必须是释放互斥的线程。在非递归互斥的情况下,没有所有权,任何线程通常都可以释放互斥,不管哪个线程最初使用互斥。在许多情况下,这种类型的“互斥”实际上是一种信号量操作,您不一定要使用互斥作为排除设备,而是将它用作两个或多个线程之间的同步或信令设备。
在评论中,人们说这是不正确的,也没有参考。所以..。
1)如果我将一个非递归互斥锁锁定在线程A中,那么线程B可以在不抓取锁的情况下解锁吗?
2)如果在锁中由线程A和线程B调用在非递归互斥中获取锁,那么线程B会等到锁被释放后才获得锁,还是会抛出异常?这种情况在递归互斥中如何?(在其他无法得出适当结论的问题中也进行了讨论)
3)当使用递归锁时,在进程终止时,是否必须释放所有递归锁?(取决于没有发生的过程结束的位置)
4)当我谨慎地使用递归锁和非递归锁的组合时,我看到了哪些问题?
PS:只使用windows平台和std::thread。
发布于 2014-10-30 14:44:28
我认为通过在Reentrant Mutexes上阅读wiki,你会得到很大的帮助。我同意另一条线索中的意见;公认的答案是错误的,或至少解释其观点非常、非常糟糕。
所有Mutexes都有所有权的概念。这就是他们不同于Semaphore的原因。锁定互斥锁的线程总是必须解锁它的线程,这是互斥锁可能导致死锁的原因之一,也是它们为预期目的工作的原因之一(以相互排除对特定代码块的访问)。
那么,递归/反射和规则互斥之间有什么区别呢?递归互斥可以被同一线程多次锁定。引用wiki的话:
递归锁(也称为递归线程互斥锁)是允许线程递归获取它所持有的相同锁的锁。请注意,此行为与普通锁不同。在正常情况下,如果一个已经持有普通锁的线程再次尝试获取相同的锁,那么它将陷入死锁。
这是两个互斥类型之间的全部差异。本质上,如果要在递归方法中放置互斥锁,并且方法在释放互斥对象之前递归,则需要递归互斥锁。否则,在第一次递归之后,将出现即时死锁,因为无法第二次获得锁。
实际上,这是使用递归互斥锁的唯一原因;大多数其他情况下,在没有释放锁的情况下,同一个线程试图获取相同的锁,很可能可以重构为正确获取/释放锁,而不需要递归互斥锁。这样做会安全得多;假设RAII,递归函数自然会冒泡并释放递归互斥锁上的每个锁,就像在其他情况下一样,您可能不会充分释放互斥锁,仍然会导致死锁。
所以,要回答你的具体问题:
注意,如果并且只有在获得的次数与所有者线程释放的次数相匹配时,递归锁才被称为释放。
发布于 2014-10-30 15:02:28
您所指的是POSIX互斥对象讨论,但Windows无论如何都不支持POSIX,您使用的是c++标准线程原语,详细内容可能有所不同。
因此,最好先检查标准库文档,例如,c++ unlock标准明确声明:
要求:调用线程将拥有互斥体。
发布于 2016-11-30 17:50:41
以下内容来自Linux pthread_mutex_lock手册页,
还可以静态地初始化pthread_mutex_t类型的变量,使用常量PTHREAD_MUTEX_INITIALIZER (用于快速互斥)、THREAD_RECURSIVE_MUTEX_INITIALIZER_NP (用于递归互斥)和PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP (用于错误检查互斥)。
在error checking'' and递归‘互斥’上,pthread_mutex_unlock实际上在运行时检查互斥锁在入口,并且被现在调用pthread_mutex_unlock的同一个线程锁定。如果不满足这些条件,则返回错误代码,互斥锁保持不变。Fast‘mutexes不执行这样的检查,从而允许锁住的互斥对象被其所有者以外的线程解锁。这是不可移植的行为,不能依赖。
看来,“非递归互斥类型的线程以外的线程可以解锁锁定的互斥锁”。
https://stackoverflow.com/questions/26655715
复制相似问题