java執行緒的狀態+鎖分析

首席菜鳥發表於2018-03-31

在最開始貼出我的執行緒狀態理解簡圖(沒畫出結束狀態):


        下面就來分析一下執行緒的整個可能出現的狀態和狀態變化出現的原因。我們都知道新建一個執行緒是很簡單的,可以通過繼承Thread或者實現Runnable/Callable介面來建立一個新的執行緒。在呼叫了start()方法之後該執行緒就進入了就緒狀態,而且在就緒狀態只能等待系統排程。在執行中的執行緒在碰到①t.join(),t.sleep(),或者是等待使用者輸入的過程就會進入阻塞狀態,只有在②join前面的執行緒執行完或者sleep時間到了和系統給與了輸入之後才能接除阻塞重新回到就緒狀態,又或者是碰到了有synchonized關鍵字鎖住的部分而且沒有獲取到鎖的時候就會進入鎖池狀態知道獲取到鎖才回到就緒狀態,當然這裡也可以理解為進入了一個同步佇列(這個稍後會再細講)。又或者是碰到了Object的wait方法或者LockSupport.park()進入一個等待佇列,當持有該物件的其他執行緒執行notify/notifyAll方法或者LockSupport.unpark()後會使其進入同步佇列,當然這裡還有一些超時的等待狀態,跟不超時的類似,這裡就不細說了。

        在前面的描述中一致有提到鎖的概念,鎖其實是JVM層提供的,每個物件都有一個monitor,當持有這個物件的monitor時我們說我們持有了這個物件的鎖。synchonized關鍵字保證了同一個時刻只能有一個執行緒持有這把鎖,它的具體實現是有monitorenter和monitorexit指令完成的,而且這兩個指令一定是成對出現的。線上程的等待通知模型裡面的執行過程如下圖(t1為等待執行緒t2為喚醒執行緒):

這也是為什麼我們說wait方法會釋放鎖的原因了。

補充:  Object的wait/notify和LockSupport的park/unpark區別:  Object的方法之間有嚴格的順序控制,如果執行順序出現變化就會得到不同的結果,但是park/unpark是針對執行緒作用,無論執行順序是否變化,最終都會執行所有執行緒程式碼。

        



相關文章