2013-12-14 65 views
2

在這本書我讀它說:需要由於原本 設置和發送通知和測試 得到通知之間存在的競爭條件爲什麼必須等待並通知從同步塊/方法中調用?

這種技術。如果wait()和notify()機制在保持同步鎖定時未調用 ,則不會保證收到通知。

不明白這究竟意味着什麼,競爭條件爲什麼會發生?

編輯:嗯,我現在看到,這可能是一個重複的問題Why must wait() always be in synchronized block ,但它接縫的答案着眼於使條件檢查,並要等待同步。從shrini1000

反例:

我還可以這樣做:
while(!condition) { synchronized(this) { wait(); } }
這意味着仍然有檢查的條件和等待,即使 如果等待()是在同步正確調用之間的競爭塊。那麼在這個限制背後還有其他什麼原因,這可能是由於它在0122中執行的 ?

+0

我不認爲答案是有的,在我的問題的反例的原因。 – croraf

+0

這裏沒有反例。您的wait()調用位於同步塊中。 – EJP

+1

其根本原因是內存模型的工作方式 - 您可以查看:http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.2詳細說明等待集如何工作。 – assylias

回答

0

事情可能被濫用的事實並不是一個反例。

Java只強制wait()notify()是同步塊的一部分(因爲這是它們應該被使用的唯一方式),但是由您來定義塊邊界。

作爲反例,請考慮finally區塊。 Java只強制它在try塊之後,但是你是唯一一個應該知道該塊應該進入哪個塊的人;你甚至可以把它留空(這會錯過finally的那一點)。

1

它必須是關於技術作者必須在您複製相關文章之前呈現的技巧。我不確定你正在閱讀哪本書,但我會試着回答這個問題。

我讀過一本類似的書「Thinking in Java」,講述了相同的競爭條件。它表明可以使用wait和notify來阻止這種情況,以便代碼不會錯過通知信號。

當使用notify()/ wait()或notifyAll( )/ wait()來協調兩個線程時,可能會錯過信號。假定T1是一個線程 通知T2,並且該兩個線程使用 以下(有缺陷的)的方式實施:

T1:

synchronized(sharedMonitor) { 
    <setup condition for T2> 
    sharedMonitor.notify(); 
} 

T2:

while(someCondition) { 
    // Assume that T2 evaluates someCondition and finds 
    // it true, now when program goes to next line thread 
    // scheduler switches to T1 and executes notify again 
    // after when control comes to T2 it blindly executes 
    // wait(), but it has already missed notify so it will 
    // always be waiting. 

    .... some code .... 

    synchronized(sharedMonitor) { 
     sharedMonitor.wait(); 
    } 
} 

(T2的設置條件)是防止T2調用wait()(如果還沒有)的動作。

解決方案是通過someCondition變量來防止競爭條件。下面是T2正確的做法:

synchronized(sharedMonitor) { 
    while(someCondition) { 
     sharedMonitor.wait(); 
    } 
} 

+0

是的,閱讀了一段時間後,我認爲這本書的作者意味着關於這種情況。這是「Java線程,第三版」。 O'Reilly,我不推薦。 – croraf

+0

希望我已經回答了您的問題。那麼你可以通過java思考(只需閱讀並行章節就足夠了解線程),更多細節jcip是最好的。 – Vipin

+0

是的,你認爲你回答了作者的意圖,但這不完全是我的問題。無論如何,我的問題並不重要。關於jcip我有這個,我會在閱讀本書後閱讀它。我會給你投票,但不是這個標記,原因;) – croraf