2012-07-18 130 views
1

有一個主線程有一個while循環,在此期間,當他檢查一些條件時,如果滿足所有條件,他將啓動另一個線程進入wait()狀態。等待並通知協調

並行運行的其他線程在工作完成時通知主線程。

當「子線程」在之前通知主線程時,主線程進入等待狀態=死鎖存在問題。

避免它的最佳做法是什麼?

回答

1

只要確保主線程不會等待已發生的事情。 (爲什麼有人會那樣做呢?這沒有任何意義。)

+1

+1:wait()的javadoc明確地解釋了應始終有一個循環檢查進入/退出等待狀態的條件。 – 2012-07-18 05:49:50

0

使用旗語的通知。

就是這樣,真的。信號量有一個計數,並可以記錄通知,直到主線程開始等待。

0

簡單的答案是使用Java 5中的併發包。CountDownLatch在這裏看起來很合適。

如果您僅限於Java 5之前的環境,則必須創建一個使用相同算法的自定義實現。創建所有子線程後,主線程將調用signalReady。子線程在完成工作後會調用signalComplete。

一個簡單的實現是將一個名爲Latch的Object帶有兩個兩個成員字段。

以下實施將適用於一位家長和一位子女。對於額外的孩子,每個孩子在完成時都可以給自己的閂鎖發出信號。仍然會有這種情況會導致競賽狀況。在信號之間添加旋轉鎖定或可能是睡眠會降低競爭條件的可能性。 它不會消除它

class Latch{ 
    Object readyLock; 
    Object completeLock; 

    public void signalComplete(){ 
    synchronized(readyLock){ 
     readyLock.wait() 
    } 
    //spin lock as a precaution 
    synchronized(completeLock){ 
     completeLock.notify() 
    } 
    } 

    public void signalReady(){ 
    synchronized(readyLock){ 
     readyLock.notify() 
    } 
    synchronized(completeLock){ 
     completeLock.wait() 
    } 
    } 
} 

希望這有助於!

+0

這段代碼被破壞嚴重,並造成OP詢問的問題!即使沒有什麼需要等待,signalReady函數也會等待。 'signalComplete'函數完成同樣的事情。 – 2012-07-18 07:18:19

0

這是一個非常普遍的做法幾乎總是wait()方法在while循環,其「迭代條件」是檢查是否已經發生特定事件時,發生其中的其他線程會被稱爲notify()方法。

例如:

while(!event_occurrence) { 
    ... 
    wait(); 
    ... 
} 

其中event_occurrence是其另一個線程會叫notify()法事件。

+0

我不認爲這將有助於:如果有2個子線程。第一個子線程完成=> event_occurrence = true,主線程進入while循環。此時(執行wait()之前)子線程2完成。那麼主線程再次執行wait()=>死鎖 – markiz 2012-07-18 07:32:12

+0

@markiz:子線程2無法完成,除非此線程處於「等待」狀態,因爲此線程持有鎖。 (它調用'wait'來釋放鎖以及等待事件。) – 2012-07-18 08:31:50

+0

@David Schwartz,鎖定主線程。子線程喚醒主線程。主線程產生子線程並等待它們中的任何一個完成。然後他做了一些邏輯並再次入睡。 – markiz 2012-07-18 09:52:44