当我使用带有1个参数的信号量时。 然后将其释放两次,它将可用许可证增加到2个,但理想情况下,我已经提到我想要1个锁。现在,由于我有2个可用许可证,因此两个线程可以获得该锁,这将破坏参数的目的。
Semaphor lock = new Semaphor(1);
lock.release();
lock.release();
lock.acquire(); // thread1
lock.acquire(); //thread2
为什么会这样?
答案 0 :(得分:1)
为什么会这样?
doc提到了它:
以这种方式使用时,二进制信号量具有属性(不同于 许多Lock实现),则“锁”可以由 所有者以外的线程(因为信号量没有 所有权)。 这在某些特殊情况下很有用,例如 死锁恢复。
您可以使用wrapper类来跟踪初始许可证。但是通常,不应该在线程release
锁定之前调用aquire
,所以它应该不会成为问题。
答案 1 :(得分:0)
release()
来自Oracle doc:释放许可证,将可用许可证数量增加一个。如果有任何线程试图获取许可,则选择一个线程并授予刚刚释放的许可。出于线程调度目的而启用了该线程。
不要求释放许可证的线程必须已经通过调用invoke()获得了该许可证。通过应用程序中的编程约定,可以正确使用信号量。
答案 2 :(得分:0)
现在,由于我有2个可用许可证,因此两个线程可以获取违反参数目的的锁。
这不会违反Semaphore
的目的。 Semaphore
的目的是实现here中所述的计数信号量抽象。
为什么
Semaphore
不尊重所提供的论点?
它确实很荣幸。但是论点并没有限制许可的数量。相反,它表示最初可以无阻碍获取的许可证数量。
为什么会这样?
因为(在Java设计人员看来)计数信号量 的行为方式。
标准Semaphore
类没有限制许可数量的方法。如果要使用锁(或二进制信号量),则应使用Lock
类...
但是在多线程应用程序中,发布和获取可能会不同步,并且最终会调用两次发布。
是的。那将是应用程序中的错误。
现在……如果您想检测到这一点,则可以扩展Semaphore
类并覆盖acquire
和release
方法,以检查许可数量是否在规定的范围内。 (如果检查失败,则可以引发未经检查的异常。或者,您可以静默忽略该请求……尽管这听起来是个坏主意。)