【多線程】線程獲取共享資源時的無鎖、偏向鎖、輕量級鎖、重量級鎖,以及它們是如何升級的呢?

鎖一共有4種狀態,級別從低到高依次是:無鎖狀態、偏向鎖狀態、輕量級鎖狀態和重量級鎖狀態,這幾個狀態會隨着競爭情況逐漸升級。鎖可以升級也可以降級,不過降級的條件特別苛刻,當JVM進入安全點(SafePoint) 的時候, 會檢查是否有閒置的Monitor, 然後試圖進行降級。

一、鎖的分類

1、⽆鎖狀態

⽆鎖就是沒有對資源進⾏鎖定,任何線程都可以嘗試去修改它

2、偏向鎖狀態

偏向鎖會偏向於第⼀個訪問鎖的線程,如果在接下來的運⾏過程中,該鎖沒有被其他的線程訪問,則持有偏向鎖的線程將永遠不需要觸發同步。
偏向鎖在資源⽆競爭情況下消除了同步語句,連CAS操作都不做,提⾼了程序的運⾏性能
偏向鎖使用了一種等到競爭出現才釋放鎖的機制,所以當其他線程嘗試競爭偏向鎖時,持有偏向鎖的線程纔會釋放鎖。偏向鎖的撤銷,需要等待全局安全點(在這個時間點上沒有正在執行的字節碼)

偏向鎖的獲得與撤銷的過程

(1)⼀個線程在第⼀次進⼊同步塊時,會在對象頭和棧幀中的鎖記錄⾥存儲鎖的偏向的
線程ID。
(2)當下次該線程進⼊這個同步塊時,會去檢查鎖的Mark Word⾥⾯是不是放
的⾃⼰的線程ID。
(3)如果是,表明該線程已經獲得了鎖,以後該線程在進⼊和退出同步塊時不需要花費
CAS操作來加鎖和解鎖
(4)如果不是,就代表有另⼀個線程來競爭這個偏向鎖。這個時候會嘗試使⽤CAS來替換Mark Word⾥⾯的線程ID爲新線程的ID,這個時候要分兩種情況:
成功,表示之前的線程不存在了, Mark Word⾥⾯的線程ID爲新線程的ID,鎖不會升級,仍然爲偏向鎖;
失敗,表示之前的線程仍然存在,那麼暫停之前的線程,設置偏向鎖標識爲0,並設置鎖標誌位爲00,升級爲輕量級鎖,會按照輕量級鎖的⽅式進⾏競爭鎖。

偏向鎖的獲得與撤銷流程圖

在這裏插入圖片描述

3、輕量級鎖狀態

多個線程在不同時段獲取同⼀把鎖,即不存在鎖競爭的情況,也就沒有線程阻塞。
針對這種情況,JVM採⽤輕量級鎖來避免線程的阻塞與喚醒。

輕量級鎖的升級過程

(1)如果⼀個線程獲得鎖的時候發現是輕量級鎖,會把鎖的Mark Word複製到⾃⼰的Displaced Mark Word⾥⾯。
(2)然後線程嘗試⽤CAS將鎖的Mark Word替換爲指向鎖記錄的指針。
如果成功,當前線程獲得鎖,
如果失敗,表示Mark Word已經被替換成了其他線程的鎖記錄,說明在與其它線程競爭鎖,當前線程就嘗試使⽤⾃旋來獲取鎖。⾃旋到⼀定程度(和JVM、操作系統相關),依然沒有獲取到鎖,稱爲⾃旋失敗,那麼這個線程會阻塞。同時這個鎖就會升級成重量級鎖

⾃旋是需要消耗CPU的,JDK採⽤了更聰明的⽅式——適應性⾃旋,簡單來說就是線程如果⾃旋成功
了,則下次⾃旋的次數會更多,如果⾃旋失敗了,則⾃旋的次數就會減少

4、重量級鎖狀態

重量級鎖依賴於操作系統的互斥量(mutex) 實現的,⽽操作系統中線程間狀態的轉換需要相對⽐較⻓的時間,所以重量級鎖效率很低,但被阻塞的線程不會消耗CPU

當調⽤⼀個鎖對象的 wait 或 notify ⽅法時,如當前鎖的狀態是偏向鎖或輕量級鎖則會先膨脹成重量級鎖

輕量級鎖及膨脹流程圖

在這裏插入圖片描述

二、鎖的升級流程

每⼀個線程在準備獲取共享資源時
(1)檢查MarkWord⾥⾯是不是放的⾃⼰的ThreadId ,如果是,表示當前線程是處於 “偏向鎖” 。
(2)如果MarkWord不是⾃⼰的ThreadId,鎖升級,這時候,⽤CAS來執⾏切換,新的線程根據MarkWord⾥⾯現有的ThreadId,通知之前線程暫停,之前線程將Markword的內容置爲空。
(3)兩個線程都把鎖對象的HashCode複製到⾃⼰新建的⽤於存儲鎖的記錄空間,接着開始通過CAS操作, 把鎖對象的MarKword的內容修改爲⾃⼰新建的記錄空間的地址的⽅式競爭MarkWord。
(4)第三步中成功執⾏CAS的獲得資源,失敗的則進⼊⾃旋 。
(5)⾃旋的線程在⾃旋過程中,成功獲得資源(即之前獲的資源的線程執⾏完成並釋放了共享資源),則整個狀態依然處於 輕量級鎖的狀態,如果⾃旋失敗 。
(6)進⼊重量級鎖的狀態,這個時候,⾃旋的線程進⾏阻塞,等待之前線程執⾏完成並喚醒⾃⼰。

三、鎖的優缺點對比

優點 缺點 使用場景
偏向鎖 加鎖和解鎖不需要額外的消耗,和執行非同步方法比僅存在納秒級的差距 如果線程間存在鎖競爭,會帶來額外的鎖撤銷的消耗 適用於只有一個線程訪問同步塊場景
輕量級鎖 競爭的線程不會阻塞,提供了程序的響應速度 如果始終得不到鎖競爭的線程,使用自旋會消耗CPU 追求響應時間,同步塊執行速度非常快
重量級鎖 線程競爭不適用自旋,不會消耗CPU 線程阻塞,響應時間緩慢 追求吞吐量,同步塊執行速度較長
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章