2016-10-18 131 views
2

嗨我對Java很新,現在我正在進入java併發。我對Synchronized方法有點懷疑:我已經看到,我可以在Synchronized方法中使用If else獲得相同的結果,每次都檢查如果執行某個操作的條件已滿足,則可以使用wait/notify方法。等待vs無等待同步方法(java)

因爲我得到了同樣的結果,我想知道如果其他方法有什麼優勢或劣勢而不是等待和通知方法?我認爲效率將是一個缺點,因爲如果總是檢查條件,誰等待只是停下來等待通知。但是還有其他的優點和缺點嗎?

Thx!

+5

你可以顯示你想要比較的代碼嗎? – Joni

+0

這些概念並不矛盾。事實上,你應該總是先檢查條件,然後再等待,否則,如果條件已經滿足,你可能會永遠等待。另一方面,如果條件未滿足,則不可能通過循環成功輪詢,因爲這將表明另一個線程在更改條件時未正確使用「synchronized」。關鍵在於,'wait'暫時釋放監視器,允許另一個線程輸入'synchronized'代碼來改變你正在等待的狀態。 – Holger

回答

1

你在混合兩個概念。如果 - 其他與Wait-Notify完全不同。你想要兩個線程與互相通信,每個其他這是其中使用Wait-Notify而if-else是一般條件語句的地方。

不能有兩個線程只需使用if-else條件相互通信。你可以編寫你的代碼,使它看起來像它一樣,但你只是不允許線程互相交互。

此外,它可能導致不良後果/計算狀態。遲早你會有hotchpotch代碼。

0

同步塊使代碼線程安全。如果您希望更高效,則您需要使用wait()notify()notifyAll()

例如,如果您的共享資源是一個列表,多個線程共享。如果你把它放在一個監視器的同步塊中,那麼在上下文切換期間,線程將不斷跳入並運行代碼。即使列表是空的!

因此,wait()用於監視器(synchronized(..)中的對象),作爲「告知」所有線程冷卻並停止使用CPU週期的機制,直到進一步通知或notifyAll()

synchronized(monitor) { 

    while(list.isEmpty()) 
     monitor.wait(); 
    doSomething(...) 
} 

在上面的例子中,doSomething()將被執行當列表不爲空,之後另一個線程執行notify()notifyAll()代碼別處。

BUT用下面的代碼:

synchronized(monitor) { 

    if(!list.isEmpty()) 
     doSomething(...) 
} 

當線程進來到同步塊中,有3種可能情況:

  1. 該列表爲空:doSomething()將會是我不會被執行。
  2. 該列表不爲空:doSomething()可能正確執行,或者...
  3. 如果在if之後和doSomething之前存在上下文切換,並且另一個線程獲取了所有列表項,則另一個上下文切換線程將在空列表上執行doSomethig()

所以,只是爲了總結一切,如果你使用wait/notify,你保證更有效的代碼!線程無法工作時,他們不需要。

+0

如果另一個線程正確使用'synchronized',場景3就不會發生,因爲這是'synchronized'塊的要點,保證其他線程不會產生干擾。另一方面,如果其他線程不能正確使用'synchronized',它也會打破基於循環的代碼,因爲在這方面'if'和'while'之間沒有根本的區別。在這兩種情況下,'doSomething(...)'在'isEmpty()'檢查之後,並依靠'synchronized'來防止兩者之間的變化。 – Holger

+0

你說得對,我只是想強調另一個可能的想法。而這是根據給定鏈接中的文檔。 –