Java 二进制信号量与可重入锁

Java 二进制信号量与可重入锁,java,multithreading,semaphore,Java,Multithreading,Semaphore,我一直试图理解可重入锁和信号量(可重入锁的嵌套与释放/解锁机制) 似乎拥有一个信号量需要编写一个经过更彻底测试的应用程序,因为release()方法不会检查释放许可证的线程是否实际持有该许可证。当我测试我的测试代码时,我发现这可能会使许可证的数量超过初始限制。另一方面,如果一个线程在调用unlock方法时没有持有可重入锁,我们会得到一个非法的monitorexception 所以说没有真正的理由使用二进制信号量是正确的,因为二进制信号量所能做的一切都可以通过可重入锁来完成。如果我们使用二进制信号

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

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

所以说没有真正的理由使用二进制信号量是正确的,因为二进制信号量所能做的一切都可以通过可重入锁来完成。如果我们使用二进制信号量,我们必须检查整个方法调用堆栈,以查看之前是否获得了许可证(如果有后续获取的可能性,许可证是否也被释放了?如果发布不继续,许可证可能会被阻止,依此类推)。此外,由于可重入锁也为每个对象提供一个锁,因此与二进制信号量相比,更倾向于使用可重入锁不是更好吗

我在这里查看了一篇文章,其中谈到了二进制信号量和互斥量之间的区别,但Java中有没有类似互斥量的东西

谢谢, 陈

另外,我已经在另一个论坛()上发布了这个问题,我还没有收到回复。我想我也应该把它贴在这里,看看我能得到什么

没有真正的理由将二进制信号量作为 二进制信号量也可以由ReentrantLock完成

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

而且,由于可重入锁也为每个对象提供一个锁,不是吗 与二进制信号量相比,选择可重入锁总是更好的主意吗

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

我查看了一篇文章,其中谈到了 二进制信号量和一个互斥体,但在这个系统中有类似互斥体的东西吗 爪哇


ReentrantLock
synchronized
是Java中互斥锁的示例。

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

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


使用java实现互斥体的另一种方法是锁支持。它的工作原理有点像信号灯,但在许可证上有一个超时,使用park()函数,一次只支持一个许可证,不像信号灯支持多个许可证。

信号灯和重入式锁之间有一些小的区别

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

这种行为可能是出于设计,并且:“不要求释放许可证的线程必须通过调用acquire()获得该许可证。信号量的正确使用由应用程序中的编程约定确定。”。使用ReentrantLocks时,必须确保在finally块中正确释放锁。这也没有强制执行,但也有很好的记录。另请参见:谢谢,约翰。这很快,也很有帮助。