为了理解计数信号量的工作,我决定实现一个简单的版本。 我想验证我当前的实现实际上是一个正确的实现,我没有错过任何明显的
public class CountingSemaphore {
private int limit;
public CountingSemaphore(int limit) {
this.limit = limit;
}
public synchronized void acquire() {
try {
if (limit == 0)
wait();
limit--;
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized void release() {
try {
if(limit == 0)
notifyAll();
limit++;
}catch(Exception e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:3)
除了一个细节外,这应该有用
由于您使用notifyAll()
,(并且由于@JBNizet指出,由于存在虚假唤醒的风险),您可以唤醒几个等待线程,所有这些线程都将被释放并减少limit
。 />
改变
if (limit == 0)
wait();
到
while (limit == 0) {
wait();
}
你应该没事。
答案 1 :(得分:3)
wait()
应始终包含在while循环中,以检查唤醒条件。请阅读the javadoc以获取更多信息。
捕捉异常并吞咽它们是一种非常糟糕的做法。您的acquire()
方法应该抛出InterruptedException。您的发布方法不应该捕获异常。
我不会将信号量本身用作锁:外部类可以使用它来同步完全不相关的东西,并且可能导致性能不佳或死锁。我会使用私有的最终锁定对象。
答案 2 :(得分:0)
从客户的角度来看,你应该强迫我使用你的信号量,其值为> = 0.
答案 3 :(得分:0)
您的代码出现问题,当您致电发布时,请致电通知所有人,但此处
public synchronized void acquire() {
try {
if (limit == 0)
wait();
limit--;
} catch (Exception e) {
e.printStackTrace();
}
}
正在等待的所有线程都被释放,你可以git limit< 0,你就可以休息了 这里常见的解决方案是使用循环。
while(limit == 0){
wait();
}