首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Android synchronized(this) 原理深度解析:監視器鎖與 happens-before

     編輯:程式設計疑難解答

語法與語義

synchronized(this) { /* 临界区 */ }
// 等价于
synchronized (this) { /* 临界区 */ }
// 实例方法加 synchronized 修饰符等价于 synchronized(this) 包裹方法体

底層實現(HotSpot JVM)

  1. 對象頭 Mark Word: 64 位 JVM 中,Mark Word 存儲 鎖狀態(無鎖/偏向鎖/輕量級鎖/重量級鎖)、線程 ID、GC 分代年齡、hashCode 等。
  2. 鎖升級流程:
    • **偏向鎖**:首次進入,CAS 將線程 ID 寫入 Mark Word,後續同線程進出零開銷。
    • **輕量級鎖**:競爭時,線程在棧桢分配 Lock Record,CAS 將 Mark Word 指向 Lock Record,自旋等待。
    • **重量級鎖**:自旋超過閾值或多線程激烈競爭,膨脹為 ObjectMonitor(C++ 實現,基於 OS Mutex/Condition Variable),線程進入 _WaitSet / _EntryList 掛起/喚醒。
  3. Monitorenter / Monitorexit 字節碼: 編譯器在同步塊首尾插入,配合 ObjectMonitor 實現互斥。

內存語義(JMM)

  • 解鎖 Happens-Before 加鎖: 線程 A 解鎖前的所有寫入,對後續加鎖同一監視器的線程 B 可見。
  • **保證可見性 + 原子性**,**不保証指令重排序**(volatile 才禁止重排)。

synchronized(this) vs synchronized(method)

維度synchronized(this)synchronized 實例方法
鎖對象當前實例當前實例
粒度控制可縮小臨界區範圍整個方法體
可讀性顯式意圖清晰隱式,易忽略

最佳實踐

  • **縮小同步塊**:只保護共享狀態讀寫,業務邏輯、I/O、睡眠移出。
  • **避免鎖對象逃逸/變更**:synchronized(list) 後 list = new ArrayList() 導致鎖失效。
  • **優先用 java.util.concurrent**:ReentrantLock、ConcurrentHashMap、LongAdder 等無鎖/細粒度鎖組件,性能更優、API 更豐富。
  • **死鎖預防**:固定獲取鎖順序、tryLock(timeout)、避免嵌套鎖。

理解 Mark Word、鎖升級、Monitor、JMM 語義,是從「會用 synchronized」進階到「能調優併發」的必經之路。

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