【问题标题】:Binary Semaphore vs a ReentrantLock二进制信号量与可重入锁
【发布时间】:2013-07-15 01:10:40
【问题描述】:

我一直在尝试理解可重入锁和信号量(可重入锁与释放/解锁机制的嵌套)。

似乎拥有 Semaphore 需要您编写一个经过更彻底测试的应用程序,因为 release() 方法不会检查释放许可的线程是否实际上持有它。当我测试我的测试代码时,我发现这可能会随后增加许可数量,超出初始限制。另一方面,如果线程在调用 unlock 方法时没有持有可重入锁,我们会得到 IllegalMonitorException。

所以说没有真正的理由拥有二进制信号量是正确的,因为二进制信号量可以做的所有事情也可以通过 ReentrantLock 来完成。如果我们使用二进制信号量,我们将不得不检查整个方法调用堆栈,以查看之前是否获得了许可(如果有可能进行后续获取,它是否也被释放 - 如果释放不继续它可能会阻塞,并且很快 )。此外,由于可重入锁也为每个对象提供一个锁,所以使用可重入锁而不是二进制信号量不是更好的主意吗?

我在这里查看了一篇关于二进制信号量和互斥量之间区别的帖子,但是在 Java 中是否有类似互斥量的东西?

谢谢, 陈。

P.S - 我已经在另一个论坛 (http://www.coderanch.com/t/615796/threads/java/reason-prefer-binary-Semaphore-Reentrant) 上发布了这个问题,但我还没有收到回复。我想我也会把它贴在这里看看我能得到什么。

【问题讨论】:

标签: java multithreading semaphore


【解决方案1】:

没有真正的理由将二进制信号量作为 二进制信号量可以做也可以通过ReentrantLock来做

如果您只需要可重入互斥,那么是的,没有理由在可重入锁上使用二进制信号量。如果出于任何原因您需要非所有权释放语义,那么显然信号量是您唯一的选择。

此外,由于可重入锁也为每个对象提供一个锁,不是吗? 与二进制信号量相比,更喜欢可重入锁总是更好的主意?

这取决于需要。如前所述,如果您需要一个简单的互斥体,则不要选择信号量。如果多个线程(但数量有限)可以进入临界区,您可以通过线程限制或信号量来实现。

我在这里查看了一篇文章,其中讨论了 二进制信号量和互斥体,但是否有类似互斥体的东西 爪哇?

ReentrantLocksynchronized 是 Java 中互斥体的示例。

【讨论】:

  • 谢谢,约翰。这既快速又有用。
【解决方案2】:

我不会解释重入锁,因为 John 已经在上面给出了一个很好的解释,它是一个 java 中的互斥锁示例以及 Synchronized 关键字。

但是,如果出于任何原因,您希望更好地控制锁定机制,Semaphore 可以变得很方便。这意味着,您的代码将不得不继续负责谁调用了 acquire() 以及谁调用了 release(),因为 Semaphore 本质上是对它视而不见的,它只关心允许变得可用。

另一种使用 java 实现互斥锁的方法是 LockSupport。它的工作方式有点像 Semaphore,但许可超时,使用 park() 函数,并且一次只支持一个许可,而 Semaphore 支持多个许可。

【讨论】:

    【解决方案3】:

    信号量和可重入锁有一些小的区别。

    • 信号量可能被另一个线程释放。 Semaphore 的 javadoc 指出,这种行为在一些特殊的上下文中可能很有用,比如死锁恢复。所以它应该是一个非常专业的上下文。
    • 二进制信号量也不能重入。您不能在同一线程中第二次获取二进制信号量。这将导致死锁(线程自身死锁!),您可能需要一些已经提到的死锁恢复方法

    【讨论】:

      猜你喜欢
      • 2014-03-07
      • 2016-11-10
      • 1970-01-01
      • 2022-11-05
      • 2020-12-23
      • 1970-01-01
      • 1970-01-01
      • 2012-10-07
      • 1970-01-01
      相关资源
      最近更新 更多