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

Java 記憶體模型(JMM)與線程安全深度解析:原子性、可見性、有序性與 Happens-Before

     編輯:Java 相關知識

JMM 三大核心特性

特性定義典型違反場景
原子性操作不可分割,執行中不被打斷i++(讀-改-寫)、32位 JVM 讀 64位 long/double
可見性一執行緒修改共享變數,其他執行緒立即可見編譯器優化缓存寄存器、指令重排、CPU 緩存一致性延遲
有序性程式執行順序符合代碼邏輯順序編譯器/CPU 指令重排(流水線優化)、單執行緒語義保證但多執行緒觀測亂序

指令重排根源

現代 CPU 採用**流水線**並行執行指令(取指→解碼→執行→存取→寫回)。為填充數據相關導致的氣泡,編譯器/CPU 會在**不違反單執行緒語義**前提下重排指令。多執行緒下可觀測到亂序。

volatile:輕量級同步基石

  • 可見性:寫入 volatile 變數立即刷新主存;讀取強制從主存載入
  • 禁止重排:寫屏障(StoreStore/StoreLoad)+ 讀屏障(LoadLoad/LoadStore)
  • 不保證原子性:volatile int i; i++; 仍非原子

Happens-Before 規則(JSR-133)

定義操作偏序關係,若 A hb B,則 A 結果對 B 可見。核心規則:

  1. 程序順序:單執行緒內代碼順序
  2. volatile 規則:寫 volatile hb 後續讀同變數
  3. 鎖規則:unlock hb 後續 lock 同鎖
  4. 傳遞性:A hb B ∧ B hb C ⇒ A hb C
  5. Thread.start() hb 執行緒內所有操作
  6. Thread.join():執行緒所有操作 hb join() 返回
  7. interrupt() hb 被中斷執行緒檢測到中斷
  8. 構造函數 完成 hb finalize()

線程安全分級

級別定義典型類
不可變狀態構造後永不改變String, Long, final 欄位物件
絕對線程安全任何調用無需外部同步ConcurrentHashMap, CopyOnWriteArrayList
相對線程安全單操作安全,複合操作需外部同步Vector, Collections.synchronizedList
線程兼容非安全,需外部同步ArrayList, HashMap
線程對立無法在多執行緒使用System.setOut, 非線程安全單例懶漢式

實戰原則

  • 優先使用不可變物件、JUC 容器
  • 複合操作(檢查-執行)用鎖或原子類(AtomicReference、LongAdder)
  • 共享變數發布用 volatile 或 final(安全發布)
  • 避免雙重檢查鎖破壞(volatile 修飾實例)
  • 掌握 happens-before 推導可見性,而非憑直覺加鎖

JMM 為 Java 併發提供了嚴格語義基石,理解其規則是編寫正確高效併發程式的前提。

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