二进制信号量与重入锁

2022-09-01 06:05:34

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

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

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

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

谢谢 陈

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


答案 1

没有真正的理由拥有二进制信号量,因为二进制信号量可以做的所有事情也可以由重入锁完成。

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

此外,由于重入锁也为每个对象提供一个锁,因此更喜欢重入锁而不是二进制信号量不是更好吗?

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

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

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


答案 2

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

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

使用java实现自己的互斥体的另一种方法是LockSupport。它的工作方式有点像Semaphore,但在许可证上有一个超时,使用park()函数,并且一次只支持一个许可证,不像信号量支持多个。