2013-03-16 58 views
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(); 
} 

的等待()實際上是由一個try-catch在兩組包圍用於捕獲線程中斷的代碼,但是爲了便於閱讀,我放棄了它,並假設它對死鎖問題沒有任何影響。

任何人有任何想法?

+1

請使用信號量提供一個簡短的*完整*程序來演示問題。 (我們不知道你是否有足夠的線程發信號通知信號量,或者「this」是什麼......) – 2013-03-16 14:10:58

+0

我不知道如何只用一個鎖就可以獲得死鎖......請注意,在你的第一個例子中你可能會錯過一個信號,因爲你使用'notify',並且你可能會因爲你的等待不在一個循環內而早早起牀。 – assylias 2013-03-16 14:14:45

+0

最初的「價值」是什麼? – jtahlborn 2013-03-16 14:17:11

回答

-1

因爲你是在後者的實施方式使用

while(value < 0) 
     wait(); 

,它是價值< 0的非無限循環中,它是循環這裏永遠。

這可能是您的死鎖情況的指針。

+2

它不會循環,只有在其他線程調用'signal'之前。 – assylias 2013-03-16 14:17:07

0

我無法發現第二次執行的任何死鎖風險。 while循環是等待鎖定的正確選擇(請參閱Object.wait() documentation中的虛假喚醒)。

此外,它看起來像沒有信號操作可以錯過。一個信號只能在另一個線程處於等待狀態,或者沒有其他線程正在運行waitFor()時發生。

因此,我建議你檢查代碼的其他部分:

  • 是否所有的線程信號量的同一實例同步?
  • 是否確定值計數器未在其他地方以 非線程安全方式使用?
  • 當 他們完成時,是否所有線程調用sepmaphore.signal()? (通常這種釋放操作放在finally塊中)。
相關問題