首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >递归和非递归锁(互斥锁)

递归和非递归锁(互斥锁)
EN

Stack Overflow用户
提问于 2014-10-30 14:30:26
回答 4查看 5.6K关注 0票数 4

在我的程序中,我的死锁有问题。所以我一直在读关于锁的文章,但问题是大多数信息都是不一致的,或者没有定义平台。在Recursive Lock (Mutex) vs Non-Recursive Lock (Mutex),最被接受的答案是:

因为递归互斥具有所有权,所以获取互斥的线程必须是释放互斥的线程。在非递归互斥的情况下,没有所有权,任何线程通常都可以释放互斥,不管哪个线程最初使用互斥。在许多情况下,这种类型的“互斥”实际上是一种信号量操作,您不一定要使用互斥作为排除设备,而是将它用作两个或多个线程之间的同步或信令设备。

在评论中,人们说这是不正确的,也没有参考。所以..。

1)如果我将一个非递归互斥锁锁定在线程A中,那么线程B可以在不抓取锁的情况下解锁吗?

2)如果在锁中由线程A和线程B调用在非递归互斥中获取锁,那么线程B会等到锁被释放后才获得锁,还是会抛出异常?这种情况在递归互斥中如何?(在其他无法得出适当结论的问题中也进行了讨论)

3)当使用递归锁时,在进程终止时,是否必须释放所有递归锁?(取决于没有发生的过程结束的位置)

4)当我谨慎地使用递归锁和非递归锁的组合时,我看到了哪些问题?

PS:只使用windows平台和std::thread

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-10-30 14:44:28

我认为通过在Reentrant Mutexes上阅读wiki,你会得到很大的帮助。我同意另一条线索中的意见;公认的答案是错误的,或至少解释其观点非常、非常糟糕。

所有Mutexes都有所有权的概念。这就是他们不同于Semaphore的原因。锁定互斥锁的线程总是必须解锁它的线程,这是互斥锁可能导致死锁的原因之一,也是它们为预期目的工作的原因之一(以相互排除对特定代码块的访问)。

那么,递归/反射和规则互斥之间有什么区别呢?递归互斥可以被同一线程多次锁定。引用wiki的话:

递归锁(也称为递归线程互斥锁)是允许线程递归获取它所持有的相同锁的锁。请注意,此行为与普通锁不同。在正常情况下,如果一个已经持有普通锁的线程再次尝试获取相同的锁,那么它将陷入死锁。

这是两个互斥类型之间的全部差异。本质上,如果要在递归方法中放置互斥锁,并且方法在释放互斥对象之前递归,则需要递归互斥锁。否则,在第一次递归之后,将出现即时死锁,因为无法第二次获得锁。

实际上,这是使用递归互斥锁的唯一原因;大多数其他情况下,在没有释放锁的情况下,同一个线程试图获取相同的锁,很可能可以重构为正确获取/释放锁,而不需要递归互斥锁。这样做会安全得多;假设RAII,递归函数自然会冒泡并释放递归互斥锁上的每个锁,就像在其他情况下一样,您可能不会充分释放互斥锁,仍然会导致死锁。

所以,要回答你的具体问题:

  1. 不,除非你的互斥系统特别允许
  2. 是的,在这两种情况下,一般来说,这是互斥实现特定于阻塞/抛出。几乎所有我使用过的系统都只是块(这就是为什么如果同一个线程在没有空闲的情况下锁两次,则非递归互斥锁会导致死锁)。
  3. 是的,通常情况下,如果适当的RAII和流程优雅地结束,它们通常会被释放。进程在持有锁的同时不优雅地终止可能会有点糟糕。
  4. 见我以上的解释。具体而言,请注意wiki中的以下内容:

注意,如果并且只有在获得的次数与所有者线程释放的次数相匹配时,递归锁才被称为释放。

票数 8
EN

Stack Overflow用户

发布于 2014-10-30 15:02:28

您所指的是POSIX互斥对象讨论,但Windows无论如何都不支持POSIX,您使用的是c++标准线程原语,详细内容可能有所不同。

因此,最好先检查标准库文档,例如,c++ unlock标准明确声明:

要求:调用线程将拥有互斥体。

票数 1
EN

Stack Overflow用户

发布于 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不执行这样的检查,从而允许锁住的互斥对象被其所有者以外的线程解锁。这是不可移植的行为,不能依赖。

看来,“非递归互斥类型的线程以外的线程可以解锁锁定的互斥锁”。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26655715

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档