为什么使用繁忙等待的信号量导致死锁?

时间:2013-03-16 14:04:05

标签: java synchronization deadlock semaphore wait

我一直在玩实现自己非常基本的信号量,并注意到我选择的实现会影响我是否会遇到死锁。但我不明白僵局是如何发生的。

我原来的实现(没有死锁):

public synchronized void waitFor(){
    value--;
    if(value < 0)
    wait();
}

public synchronized void signal(){
    value++;
    notify();
}

稍后的实现(导致死锁):

public synchronized void waitFor(){
    value--;
    while(value < 0)
        wait();
}

public synchronized void signal(){
    value++;
    notifyAll();
}

在两组用于捕获线程中断的代码中,wait()实际上都被try-catch所包围,但为了便于阅读,我把它留了下来,并假设它对死锁问题没有任何影响。

有人有什么想法吗?

2 个答案:

答案 0 :(得分:0)

我无法发现第二次实施的任何死锁风险。 while循环是等待锁定的正确选择(参见Object.wait() documentation中的虚假唤醒)。

此外,看起来不会错过任何信号操作。只有当另一个线程处于等待状态,或没有其他线程正在运行时才会发生信号waitFor()。

因此,我建议您检查代码的其他部分:

  • 是否所有线程都在同一个信号量实例上同步?
  • 您确定价值计数器未在其他地方使用吗? 非线程安全的方式?
  • 当所有线程调用sepmaphore.signal()时 他们完成了吗? (通常这种释放操作放在finally块中。)

答案 1 :(得分:-1)

正在使用

while(value < 0)
        wait();

在后一个实现中,它位于值<0的非结束循环中,并且它永远在这里循环。

这可能是你死锁情况的指针。