Java 內存模型 (JMM) 是並發編程的基石,定義了線程與主內存交互的語義規範。本文系統梳理 JMM 核心概念(主內存/工作內存、八大操作、volatile/long/double 特殊規則)、三大特性(原子性/可見性/有序性)、以及 Happens-Before 八大法則,構建並發正確性推理的理論基石。
| 操作 | 作用對象 | 語義 | 配對關係 |
|---|---|---|---|
| lock (鎖定) | 主內存變量 | 標識變量為線程獨佔 | lock/unlock 配對 |
| unlock (解鎖) | 主內存變量 | 釋放獨佔狀態,允許其他線程鎖定 | |
| read (讀取) | 主內存變量 | 從主內存傳輸值到線程緩存 | read/load 配對 |
| load (載入) | 工作內存變量 | 將 read 獲取的值放入工作內存副本 | |
| use (使用) | 工作內存變量 | 將工作內存值傳遞給執行引擎 | use/assign 配對 |
| assign (賦值) | 工作內存變量 | 將執行引擎接收的值賦給工作內存副本 | |
| store (存儲) | 工作內存變量 | 將工作內存值傳輸到主內存緩存 | store/write 配對 |
| write (寫入) | 主內存變量 | 將 store 獲取的值寫入主內存變量 |
volatile int i; i++) 仍非原子,需配合 AtomicInteger 或 synchronizedvolatile 修飾的 64 位讀寫拆分為兩次 32 位操作load/store/read/write 四操作可不保證 64 位原子性
AtomicLong/AtomicDouble/LongAdder/DoubleAdder| 特性 | 定義 | JMM 保障機制 | 典型手段 |
|---|---|---|---|
| 原子性 | 操作不可分割,要么全做要么全不做 | 八大操作本身原子;synchronized/Lock 保證代碼塊原子 | synchronized、Lock、Atomic*、CAS |
| 可見性 | 線程修改共享變量,其他線程立即可見 | volatile 強制刷新/失效緩存;synchronized/unlock 同步回主內存 | volatile、synchronized、final、Lock |
| 有序性 | 程序執行順序符合預期 | as-if-serial 語義 (單線程);happens-before 規則 (多線程) | volatile、synchronized、final、Lock |
核心洞察:單線程內表現為有序 (as-if-serial);多線程觀察彼此則表現為無序 (指令重排、緩存延遲)。JMM 通過 happens-before 建立跨線程的有序性承諾。
若操作 A happens-before 操作 B,則 A 的影響 (內存寫入、消息發送、方法調用等) 對 B 可見。
| 法則 | 規則描述 | 典型場景 |
|---|---|---|
| 1. 程序次序規則 | 單線程內,按控制流順序 (非代碼行順序,含分支/循環),前面操作 HB 後面操作 | 單線程邏輯推理基礎 |
| 2. 管程鎖定規則 | unlock 操作 HB 後續對同一鎖的 lock 操作 | synchronized/lock 保護的臨界區互斥與內存同步 |
| 3. volatile 變量規則 | 對 volatile 寫操作 HB 後續對同一變量的讀操作 | 狀態標誌位、雙重檢查鎖單例 |
| 4. 線程啟動規則 | Thread.start() HB 線程內所有操作 | 主線程初始化數據,子線程可見 |
| 5. 線程終止規則 | 線程內所有操作 HB 線程終止檢測 (Thread.join()/isAlive()) | 主線程等待子線程結果 |
| 6. 線程中斷規則 | interrupt() 調用 HB 被中斷線程檢測到中斷 (interrupted()/isInterrupted()) | 優雅停止線程 |
| 7. 對象終結規則 | 對象構造函數執行結束 HB finalize() 方法開始 | 對象銷毀前清理 |
| 8. 傳遞性 | A HB B 且 B HB C → A HB C | 跨多個同步動作鏈路傳遞可見性 |
public class Singleton {
private volatile static Singleton instance; // 關鍵:volatile
public static Singleton getInstance() {
if (instance == null) { // 1. 讀取 instance (volatile read)
synchronized (Singleton.class) { // 2. lock
if (instance == null) { // 3. 讀取 instance (volatile read)
instance = new Singleton(); // 4. 構造對象 + 寫入 instance (volatile write)
}
} // 5. unlock
}
return instance; // 6. 讀取 instance (volatile read)
}
}
instance = new Singleton() (步驟 4),包含:分配內存、初始化對象、將引用寫入 instance (volatile write)volatile:步驟 4 可能重排序為 (分配內存 → 寫入引用 → 初始化對象),線程 B 讀到非 null 但未初始化完成的引用 → 空指針/數據錯誤JMM 通過「主/工作內存抽象、八大原子操作、操作約束規則、特殊類型語義」定義了並發語義基礎;通過「原子性/可見性/有序性」三大特性刻畫並發正確性要求;通過「Happens-Before 八大法則」提供跨線程可見性與有序性的形式化推理工具。掌握 JMM 核心規範,能從理論層面證明 volatile/synchronized/final/Lock 等並發手段的正確性邊界,指導無鎖算法設計、並發 Bug 根因分析、高性能並發組件構建。建議開發者熟練運用 HB 圖推理並發代碼正確性,將並發編程從「經驗堆砌」提升到「數學證明」層級。