gpt4 book ai didi

multithreading - 递归锁(互斥锁)与非递归锁(互斥锁)

转载 作者:行者123 更新时间:2023-12-03 04:15:19 29 4
gpt4 key购买 nike

POSIX 允许互斥体是递归的。这意味着同一个线程可以两次锁定同一个互斥锁,并且不会死锁。当然也需要解锁两次,否则其他线程都无法获取互斥锁。并非所有支持 pthread 的系统也支持递归互斥体,但如果它们想成为 POSIX conform, they have to .

其他 API(更高级的 API)通常也提供互斥体,通常称为锁。一些系统/语言(例如 Cocoa Objective-C)提供递归和非递归互斥体。有些语言也只提供其中一种。例如。在Java中,互斥体总是递归的(同一个线程可能在同一个对象上两次“同步”)。根据它们提供的其他线程功能,没有递归互斥体可能没有问题,因为它们可以轻松地自己编写(我自己已经在更简单的互斥体/条件操作的基础上实现了递归互斥体)。

我不太明白:非递归互斥锁有什么用?如果两次锁定同一个互斥锁,为什么会出现线程死锁?即使是可以避免这种情况的高级语言(例如,测试这是否会死锁,如果发生则抛出异常)通常也不会这样做。他们会让线程死锁。

这只适用于我不小心锁定它两次并且只解锁一次的情况,并且在递归互斥体的情况下,很难找到问题,所以我立即让它死锁以查看不正确的锁定在哪里出现?但是,我不能在解锁时返回一个锁计数器吗?在我确信我释放了最后一个锁并且计数器不为零的情况下,我可以抛出异常或记录问题吗?或者还有其他我看不到的更有用的非递归互斥体用例吗?或者这可能只是性能问题,因为非递归互斥体可能比递归互斥体稍快一些?不过我测试了一下,差别确实没那么大。

最佳答案

递归互斥体和非递归互斥体之间的区别与所有权有关。在递归互斥体的情况下,内核必须跟踪第一次实际获得互斥体的线程,以便它可以检测递归与应该阻塞的不同线程之间的差异。正如另一个答案指出的那样,存在存储此上下文的内存以及维护它所需的周期方面的额外开销的问题。

但是,这里还有其他考虑因素。

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

互斥体中具有所有权感的另一个属性是支持优先级继承的能力。由于内核可以跟踪拥有互斥锁的线程以及所有阻塞程序的身份,因此在优先级线程系统中,可以将当前拥有互斥锁的线程的优先级升级为最高优先级线程的优先级当前正在互斥体上阻塞。这种继承可以防止在这种情况下可能发生的优先级反转问题。 (请注意,并非所有系统都支持此类互斥体上的优先级继承,但这是通过所有权概念成为可能的另一个功能)。

如果你引用经典的VxWorks RTOS内核,它们定义了三种机制:

  • 互斥体 - 支持递归和可选的优先级继承。这种机制通常用于以一致的方式保护数据的关键部分。
  • 二进制信号量 - 无递归,无继承,简单排除,接受者和给予者不必是同一线程,可用广播释放。这种机制可用于保护关键部分,但对于线程之间的一致信号或同步也特别有用。
  • 计数信号量 - 无递归或继承,充当任何所需初始计数的连贯资源计数器,线程仅在资源净计数为零的情况下阻塞。

同样,这会因平台而有所不同 - 特别是他们如何称呼这些东西,但这应该代表正在发挥作用的概念和各种机制。

关于multithreading - 递归锁(互斥锁)与非递归锁(互斥锁),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/187761/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com