2013-07-16 36 views
23

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

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

因此,如果说没有任何真正的理由会产生二进制信号量,那么二进制信号量所能做的所有事情都可以通过ReentrantLock来完成。如果我们使用二进制信号量,我们将不得不检查整个方法调用堆栈以查看是否获得了许可证(如果有后续获取的可能性,它也会被释放 - 如果发布版本不能继续发布它,则可能会阻止它;等等)。另外,因为可重入锁也为每个对象提供一个锁,所以将一个可重入锁置于二进制信号量不是一个更好的办法吗?

我已经在这里检查了一篇文章,讨论二进制信号量和互斥量之间的区别,但是有没有像Java中的互斥量那样的东西?

谢谢, 陈。

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

+0

http://stackoverflow.com/questions/12641933/difference-between-semaphore-and-condition-reentrantlock可能有帮助 – 2013-07-16 17:52:33

+2

该行为是由设计和[记录良好](http://docs.oracle.com/ javase/7/docs/api/java/util/concurrent/Semaphore.html#release%28%29):“*没有要求释放许可的线程必须通过调用acquire()来获得许可。通过编程约定在应用程序中建立信号量的使用。*“。使用ReentrantLocks时,您必须确保您在finally块中正确释放您的锁。这不是强制执行,但也有很好的文件记录。 – assylias

+1

另见:http://stackoverflow.com/questions/7554839/how-and-why-can-a-semaphore-give-out-more-permits-than-it-was-initialized-with – assylias

回答

25

没有真正的理由曾经有一个二进制信号作为一切,一个 二进制信号可以做,也可以通过一个ReentrantLock的

做。如果你需要的是再进入的互斥,那么是的,没有理由在ReentrantLock上使用二进制信号量。如果因为任何原因你需要非所有权释放语义,那么明显的信号量是你唯一的选择。

此外,由于折返锁还提供了每个对象一个锁,是不是 总是一个更好的主意,喜欢重入锁二进制信号?

这取决于需要。就像之前解释的那样,如果你需要一个简单的互斥量,那么不要选择一个信号量。如果多个线程(但数量有限)可以进入关键部分,则可以通过线程约束或信号量来完成。

我已经检查了这里后,一个 二进制信号量和互斥之间谈论的差异,但有一件事像 Java中的互斥?

ReentrantLock和​​是Java中的互斥体的示例。

+1

谢谢,约翰。这很快且很有帮助。 – Chan

3

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

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

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