我一直在努力了解Reentrant锁和信号量(重入锁定与释放/解锁机制的嵌套)。
似乎有一个信号量要求你编写一个更彻底测试的应用程序,因为release()方法不会检查释放许可证的线程是否实际上持有它。当我测试我的测试代码时,我发现这可能随后增加超出初始限制的许可数量。另一方面,如果一个线程在调用unlock方法时没有持有重入锁,我们会得到一个IllegalMonitorException。
所以说没有真正的理由拥有二进制信号量是正确的,因为二进制信号量可以做的所有事情也可以由ReentrantLock完成。如果我们使用二进制信号量,我们必须检查整个方法调用堆栈以查看之前是否获得了许可证(如果有可能进行后续获取,它也会被释放 - 如果某个版本没有继续获取它可能会阻止它等等)。此外,由于重入锁也为每个对象提供一个锁,所以更喜欢将重入锁定为二进制信号量并不总是更好吗?
我在这里查了一篇文章,讨论二进制信号量和互斥量之间的区别,但有没有像Java中的互斥量这样的东西?
谢谢, 陈。
P.S - 我在另一个论坛(http://www.coderanch.com/t/615796/threads/java/reason-prefer-binary-Semaphore-Reentrant)发布了这个问题,但我还没有收到回复。我想我也会在这里发布,看看能得到什么。
答案 0 :(得分:33)
没有任何理由可以将二进制信号量作为a的所有内容 二进制信号量可以做的也可以通过ReentrantLock
来完成
如果您只需要可重入互斥,那么是的,没有理由在ReentrantLock上使用二进制信号量。如果由于任何原因您需要非所有权释放语义,那么显然信号量是您唯一的选择。
此外,由于重入锁也为每个对象提供一个锁,因此不是 总是更喜欢将重入锁定转换为二进制信号量?
这取决于需要。如前所述,如果您需要一个简单的互斥锁,那么就不要选择信号量。如果多个线程(但数量有限)可以进入临界区,则可以通过线程限制或信号量来执行此操作。
我在这里查了一篇关于a之间差异的帖子 二进制信号量和互斥量,但有一个像互斥量的东西 爪哇?
ReentrantLock
和synchronized
是Java中互斥体的示例。
答案 1 :(得分:6)
我不会解释重入锁定,因为John已经在上面给出了一个很好的解释,并且它是java中的互斥锁示例以及Synchronized关键字。
但是,如果出于任何原因,您希望更好地控制锁定机制,Semaphore可以变得方便。这意味着,您的代码将不得不继续负责调用acquire()和调用release()的人,因为Semaphore本质上是盲目的,所有它关心的是许可变得可用。
使用java自己的互斥体实现的另一种方法是LockSupport。它的工作方式有点像信号量,但是在许可证上有一个超时,使用park()函数,并且一次只支持一个许可证,不像支持多个信号量的信号量。
答案 2 :(得分:0)
信号量和可重入锁之间有一些细微差别。