偏向鎖,輕量級鎖,重量級鎖的加鎖過程


https://blog.csdn.net/lengxiao1993/article/details/81568130

Java SE1.6 為了改善性能, 使得 JVM 會根據競爭情況, 使用如下 3 種不同的鎖機制

  • 偏向鎖(Biased Lock )
  • 輕量級鎖( Lightweight Lock)
  • 重量級鎖(Heavyweight Lock)

上述這三種機制的切換是根據競爭激烈程度進行的, 在幾乎無競爭的條件下, 會使用偏向鎖, 在輕度競爭的條件下, 會由偏向鎖升級為輕量級鎖, 在重度競爭的情況下, 會升級到重量級鎖。

1.偏向鎖

注意 JVM 提供了關閉偏向鎖的機制, JVM 啟動命令指定如下參數即可-XX:-UseBiasedLocking


根據偏斜鎖機制是否打開, 對象 MarkWord 狀態以不同方式轉換的過程


無鎖 -> 偏向鎖

偏向鎖的獲取方式是將對象頭的 MarkWord 部分中, 標記上線程ID, 以表示哪一個線程獲得了偏向鎖。

1.如果為可偏向狀態, 則嘗試用 CAS 操作, 將自己的線程 ID 寫入MarkWord

  • 如果 CAS 操作成功(狀態轉變為下圖), 則認為已經獲取到該對象的偏向鎖, 執行同步塊代碼 。
  • 補充: 一個線程在執行完同步代碼塊以后, 並不會嘗試將 MarkWord 中的 thread ID 賦回原值 。這樣做的好處是: 如果該線程需要再次對這個對象加鎖,而這個對象之前一直沒有被其他線程嘗試獲取過鎖,依舊停留在可偏向的狀態下, 即可在不修改對象頭的情況下, 直接認為偏向成功。

如果 CAS 操作失敗, 則說明, 有另外一個線程 Thread B 搶先獲取了偏向鎖。 這種狀態說明該對象的競爭比較激烈, 此時需要撤銷 Thread B 獲得的偏向鎖,將 Thread B 持有的鎖升級為輕量級鎖。 該操作需要等待全局安全點 JVM safepoint ( 此時間點, 沒有線程在執行字節碼)。

2.如果是已偏向狀態, 則檢測 MarkWord 中存儲的 thread ID 是否等於當前 thread ID 。

  • 如果相等, 則證明本線程已經獲取到偏向鎖, 可以直接繼續執行同步代碼塊

如果不等, 則證明該對象目前偏向於其他線程, 需要撤銷偏向鎖

 

偏向鎖的撤銷(Revoke)

如上文提到的, 偏向鎖的撤銷(Revoke) 操作並不是將對象恢復到無鎖可偏向的狀態, 而是在偏向鎖的獲取過程中, 發現了競爭時, 直接將一個被偏向的對象“升級到” 被加了輕量級鎖的狀態。 這個操作的具體完成方式如下:

  • 在偏向鎖 CAS 更新操作失敗以后, 等待到達全局安全點。

通過 MarkWord 中已經存在的 Thread Id 找到成功獲取了偏向鎖的那個線程, 然后在該線程的棧幀中補充上輕量級加鎖時, 會保存的鎖記錄(Lock Record), 然后將被獲取了偏向鎖對象的 MarkWord 更新為指向這條鎖記錄的指針。

 

偏向鎖 -> 輕量級鎖

從之前的描述中可以看到, 存在超過一個線程競爭某一個對象時, 會發生偏向鎖的撤銷操作。 有趣的是, 偏向鎖撤銷后, 對象可能處於兩種狀態。

一種是不可偏向的無鎖狀態, 如下圖(之所以不允許偏向, 是因為已經檢測到了多於一個線程的競爭, 升級到了輕量級鎖的機制)

另一種是不可偏向的已鎖 ( 輕量級鎖) 狀態

之所以會出現上述兩種狀態, 是因為偏向鎖不存在解鎖的操作, 只有撤銷操作。 觸發撤銷操作時:

  • 原來已經獲取了偏向鎖的線程可能已經執行完了同步代碼塊, 使得對象處於 “閑置狀態”,相當於原有的偏向鎖已經過期無效了。此時該對象就應該被直接轉換為不可偏向的無鎖狀態

原來已經獲取了偏向鎖的線程也可能尚未執行完同步代碼塊, 偏向鎖依舊有效, 此時對象就應該被轉換為被輕量級加鎖的狀態

 

輕量級加鎖過程:

    • 首先根據標志位判斷出對象狀態處於不可偏向的無鎖狀態( 如下圖)
      這里寫圖片描述
    • 在當前線程的棧楨(Stack Frame)中創建用於存儲鎖記錄(lock record)的空間,並將對象頭中的Mark Word復制到鎖記錄中,官方稱為Displaced Mark Word。如果在此過程中發現,
    • 然后線程嘗試使用 CAS 操作將對象頭中的 Mark Word 替換為指向鎖記錄的指針。
      • 如果成功,當前線程獲得鎖
      • 如果失敗,表示該對象已經被加鎖了, 先進行自旋操作, 再次嘗試 CAS 爭搶, 如果仍未爭搶到, 則進一步升級鎖至重量級鎖。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM