0

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

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

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 包围,用于捕获线程中断,但为了便于阅读,我将其省略了,并假设它对死锁问题没有影响。

有人有想法么?

4

2 回答 2

0

我无法发现第二个实现有任何死锁风险。while 循环是等待锁的正确选择(请参阅Object.wait() 文档中的虚假唤醒)。

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

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

  • 所有线程是否在同一信号量实例上同步?
  • 您确定值计数器没有以非线程安全的方式在其他地方使用吗?
  • 所有线程在完成后都会调用 semaphore.signal() 吗?(通常这种释放操作放在 finally 块中)。
于 2013-03-16T14:36:30.427 回答
-1

当你使用

while(value < 0)
        wait();

在您的后一个实现中,它位于 value <0 的非结束循环中,并且它永远在此处循环。

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

于 2013-03-16T14:14:48.290 回答