简单计数信号量

时间:2012-09-24 19:33:44

标签: java concurrency semaphore

为了理解计数信号量的工作,我决定实现一个简单的版本。 我想验证我当前的实现实际上是一个正确的实现,我没有错过任何明显的

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();
        }
    }

}

4 个答案:

答案 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();
}