首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 並發編程:Synchronized 底層優化機制深度解析

     編輯:Java 相關知識

Java 並發編程:Synchronized 底層優化機制深度解析

synchronized 通過對象頭的監視器鎖實現,底層依賴 OS 的 Mutex Lock,用戶態/核心態切換開銷大,稱為「重量級鎖」。JDK 1.6 引入「輕量級鎖」和「偏向鎖」優化。

鎖狀態與對象頭標記 (32位 JVM)

鎖狀態標記位是否偏向鎖對象頭內容
無鎖010對象 hashCode + 分代年齡
偏向鎖011線程 ID + Epoch + 分代年齡
輕量級鎖00-指向棧中鎖記錄的指針
重量級鎖10-指向互斥量的指針
GC 標記11-空

輕量級鎖

適用場景:線程交替執行同步塊,無競爭。

加鎖流程

  1. 進入同步塊,對象無鎖 → 當前線程棧幀建立「鎖記錄」,複製對象 Mark Word 為「Displaced Mark Word」。
  2. CAS 更新對象 Mark Word 指向鎖記錄,成功則獲得鎖,標記位設為 00。
  3. CAS 失敗 → 檢查 Mark Word 是否指向當前線程棧幀(重入),否則升級為重量級鎖,標記位 10,其他線程阻塞並自旋嘗試獲取。

解鎖流程

  1. CAS 將 Displaced Mark Word 替換回對象 Mark Word。
  2. 成功 → 同步結束。失敗 → 鎖已膨脹,喚醒被掛起線程。

偏向鎖

適用場景:無多線程競爭,同一線程反覆進入同步塊。消除 CAS 開銷,僅需一次 CAS 設置 ThreadID。

獲取流程

  1. 檢查 Mark Word 偏向鎖標識為 1、鎖標記 01 → 可偏向狀態。
  2. ThreadID 指向當前線程 → 直接進入同步塊。
  3. 否則 CAS 競爭鎖,成功設 ThreadID,失敗表示有競爭 → 撤銷偏向鎖,升級輕量級鎖。

撤銷機制

遇其他線程競爭時,在全局安全點掛起持有線程,恢復到無鎖或輕量級鎖狀態。線程不會主動釋放偏向鎖。

三種鎖轉換關係

無鎖 → 偏向鎖 → 輕量級鎖 → 重量級鎖(單向升級,不降級)

其他 JVM 優化

  • 適應性自旋:自旋成功增加次數,失敗減少次數,避免 CPU 空轉。
  • 鎖粗化:連續加鎖/解鎖合併為一次大範圍鎖(如 StringBuilder 連續 append)。
  • 鎖消除:逃逸分析發現數據不逃逸出線程,判定為線程安全,自動刪除鎖(如方法內部 StringBuffer)。

鎖選型對比表

鎖類型優點缺點適用場景
偏向鎖加/解鎖無額外開銷,與非同步方法差距納秒級有競爭時撤銷開銷大單線程訪問同步塊
輕量級鎖競爭線程不阻塞,提升響應速度自旋消耗 CPU追求響應時間,同步塊執行極快
重量級鎖不自旋不消耗 CPU線程阻塞,響應慢追求吞吐量,同步塊執行較長

激烈競爭下偏向鎖反而降低效能,可用 -XX:-UseBiasedLocking 禁用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved