2016-04-26 79 views
4

Java線程中Java線程的狀態可以通過舉行:什麼是等待,無法獲得鎖

  1. 無法獲取的鎖。
  2. 正在通過wait()方法舉行。

以上兩種情況在Java線程狀態方面有什麼區別?

考慮以下簡單的代碼:

synchronized(object) { 
     object.wait(); 
     System.out.println("Completed."); 
    } 

如果兩個線程(說的ThreadA和ThreadB)都被關押在wait()方法。例如,當另一個線程調用notifyAll()時,ThreadA將從等待中恢復並獲取對象的鎖定並繼續。 ThreadB也會復活,但無法獲取對象的鎖定並保持到ThreadA退出同步塊爲止。 ThreadB然後獲得鎖並繼續。

其結果將是兩個「已完成」被打印。

在這個例子中,必須有當從ThreadB變化「正在舉行的wait()」到「正在舉行,因爲它是無法獲得對象的鎖」的時間。

我想知道它是如何工作的內部Java編寫的。請幫忙。

+2

基於'enum Thread.State'的Javadoc(我還沒有試過實驗),狀態應該從'WAITING'變成'BLOCKED'。也許你可以做實驗,看看我是否正確。 –

+1

這個[answer](http://stackoverflow.com/a/28726421/6238076)已經非常詳細地解釋了所有等待線程在收到通知後的行爲。 – gdlmx

回答

2

的區別是在object.wait()狀態釋放object所有的顯示器所持有的該線程,它會在系統中重新獲取所有的線程競爭再次監視。這使得wait()成爲特殊狀態。

所以你的情況時AB(線程A和線程B)處於觀望狀態,他們沒有監視器同步object,他們都已經從執行暫停,直到其他線程調用object.notify()object.notifyAll()。當notifyAll()被稱爲JVM喚醒所有線程(在這種情況下AB)在object.wait()狀態和他們競爭,以獲得當前​​塊的監視器。如果調用notify(),則JVM隨機選取A或B.

這是這裏要注意的是,JVM沒有通知任何特定的線程,這就是爲什麼每一個等待的線程在一個while(notify_condition_for_me)循環等待,即驗證如果等待病情已如果沒有它在object.wait()狀態去再次。

所以正確的代碼應該是

synchronized(object) { 
    while(myResourceArrived) {//like URL data, JDBC data or something 
     object.wait(); 
    } 
    System.out.println("Completed."); 
} 

ABobject.wait()狀態,他們已經釋放了所有他們之前持有object這是等待​​塊之外的顯示器,所以任何其他線程將通過獲取object的已發佈顯示器立即能夠進入該區塊。

2

看看Thread.State,更具體地說WAITINGBLOCKED狀態。

如果您對內部實現感興趣,都可以使用LockSupport.park()LockSupport.unpark(Thread)來實現,而實際上它們是如何在大多數地方實現的。

P.S.如果你有興趣,這裏是在OpenJDK park()實現了Windows (line 4946)Linux (line 5808),這裏是wait()/notify()/notifyAll()執行(1457線)。他們有很好的評論,如果一看起來太複雜,就給它一些時間。在object.wait()狀態,並等待object監視器上的鎖福利之間