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

JVM 核心知識體系(三):Java 內存模型(JMM)完整總結與 volatile 實戰

     編輯:Java 綜合教學

JVM 核心知識體系(三):Java 內存模型(JMM)完整總結與 volatile 實戰

Java 內存模型(JMM)定義了線程與主內存之間的交互規範,是並發編程正確性的基石。本文系統總結 JMM 核心概念、volatile 語義、三大特性(原子性、可見性、有序性)、happens-before 原則及指令重排。

一、為什麼需要 JMM?

現代 CPU 多核架構下,各核心擁有私有高速緩存,導致緩存一致性問題。JMM 屏蔽硬體/OS 差異,規範 JVM 變量在主內存與線程工作內存間的讀寫協議,保證跨平台並發行為一致。

物理機緩存一致性模型

二、JMM 抽象結構

  • 主內存:存儲所有共享變量(堆中對象實例、靜態字段、數組元素)。
  • 工作內存:每條線程私有,保存主內存變量的副本(對應棧幀局部變量表)。
  • 線程只能操作工作內存,變量同步需經主內存中轉。

JMM 主內存與工作內存交互

三、內存交互八大原子操作

read、load、use、assign、store、write、lock、unlock。單個操作原子,但操作序列可被打斷。

四、volatile 關鍵字深度解析

核心語義

  1. 可見性:寫入 volatile 變量立即刷新至主內存,讀取時強制從主內存加載,其他線程立即可見。
  2. 禁止指令重排:寫入前的操作不會被重排到寫入後,讀取後的操作不會被重排到讀取前。

經典失效案例:非 volatile 導致死循環

// 線程 A
boolean stop = false;
while (!stop) { doSomething(); }

// 線程 B
stop = true; // 未加 volatile,A 可能永遠看不到更新

非 volatile 線程通信流程

加上 volatile 後,B 寫入強制刷主存並使 A 工作內存緩存行失效,A 重讀獲取最新值,循環正常終止。

使用條件

  • 寫入不依賴當前值(如 i++ 非原子,不可用 volatile)。
  • 不包含在不變式中(如需與其他變量配合檢查)。

典型適用:boolean 狀態標誌、單獨的 long/double 讀寫(JDK 5+ 保證 64 位原子)。

五、JMM 三大特性

特性定義實現手段
原子性操作不可分割,要麼全做要麼全不做synchronized、Lock、基本類型讀寫(除 64 位非 volatile)
可見性一線程修改,他線程立即可見volatile、synchronized(unlock 前刷主存)、final(初始化後可見)
有序性本線程內有序,跨線程可能無序volatile(禁止重排)、synchronized(鎖串行化)、happens-before 規則

六、指令重排與 happens-before 原則

編譯器/處理器為優化性能會重排無數據依賴的指令。JMM 通過 happens-before 規則約束重排:

  1. 程序次序規則:單線程內代碼順序前行 happens-before 後行(單線程語義不變)。
  2. 鎖定規則:unlock happens-before 後續同一鎖的 lock。
  3. volatile 變量規則:寫 volatile happens-before 後續讀同一 volatile。
  4. 傳遞性:A hb B 且 B hb C ⇒ A hb C。
  5. 線程啟動、中斷、終結、對象終結規則。

重排經典案例

// 線程 A
a = 1; flag = true;

// 線程 B
if (flag) { int i = a + 1; } // 可能讀到 a=0,因為 A 可能重排為 flag=true; a=1;

指令重排導致跨線程無序

解決:將 flag 聲明為 volatile,或雙方加同步鎖(利用鎖定規則)。

七、C/C++ 內存模型對比

C/C++ 早期標準無內建線程模型,依賴 pthreads 等庫與編譯器/硬體保障。C++11 才引入標準內存模型(std::atomic、memory_order),與 JMM 理念相近但更底層靈活。

八、字節碼執行模式:解釋執行 vs JIT 編譯執行

  • 解釋執行:逐行讀取字節碼解釋執行,啟動快、峰值性能低。
  • JIT 編譯執行:熱點代碼編譯為機器碼直接執行,性能提升數量級(10x+)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved