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

Java 內存模型 (JMM) 深度總結:從處理器內存模型、happens-before 到 volatile/final 語義增強

     編輯:Java 綜合教學

三層內存模型關係圖

  
    模型典型處理器Store-LoadStore-StoreLoad-Load/Load-Store備註
  
  
    TSOx86, SPARC-TSOY--僅允許寫-讀重排
    PSOSPARC-PSOYY-允許寫-寫重排
    RMOIA64YYY允許讀-讀/讀-寫重排
    PowerPCPowerPCYYY最弱,全重排
  

關鍵點: 所有處理器都允許 Store-Load 重排 (寫緩衝區導致);JMM 在字節碼中插入 內存屏障 抑制非法重排,屏蔽硬件差異。

JMM 設計核心:happens-before 規則

happens-before 是 JMM 向程序員承諾的可見性與有序性契約:若 A hb B,則 A 的寫入對 B 可見,且 A 執行順序在 B 之前。

八大天然 happens-before 規則

  1. 程序順序規則: 線程內按代碼順序 (控制流順序)。
  2. 鎖規則: unlock hb 後續對同一鎖的 lock。
  3. volatile 規則: 寫 volatile hb 後續讀同一 volatile。
  4. 線程啟動規則: Thread.start() hb 線程內任何動作。
  5. 線程終結規則: 線程內所有動作 hb Thread.join() 返回。
  6. 線程中斷規則: interrupt() hb 被中斷線程檢測到中斷。
  7. 對象終結規則: 構造函數結束 hb finalize() 開始。
  8. 傳遞性: A hb B 且 B hb C → A hb C。

編譯器/處理器優化邊界

JMM 允許不改變單線程語義且正確同步的多線程程序結果的重排序。對於 double pi=3.14; double r=1.0; double area=pi*r*r;,pi 與 r 賦值可重排 (無數據依賴),但 area 必須在兩者之後 (數據依賴)。

JSR-133 (Java 5) 關鍵修補

1. volatile 語義增強:禁止 volatile 與普通變量重排

class FinalDemo {
    final int x;           // 最終字段
    static FinalDemo obj;
    void writer() { obj = new FinalDemo(1); }  // 構造函數寫 final
    void reader() { 
        FinalDemo o = obj;  // 讀引用
        if (o != null) System.out.println(o.x); // 保證讀到 1,不會讀到 0
    }
}

兩條重排序規則:

  1. 構造函數內對 final 域寫入,不得重排序到構造函數外 (對其他線程可見)。
  2. 初次讀對象引用,不得重排序到 final 域讀取之前。

結果:final 具有初始化安全性,無需同步即可安全發布不可變對象。

三類程序的可見性保證對比

程序類型順序一致性模型JMM說明
單線程一致一致as-if-serial 語義保證
正確同步多線程一致一致JMM 核心承諾:data-race-free → SC
未同步/錯誤同步多線程未定義未定義JMM 不承諾任何可見性

內存屏障插入策略 (JMM → 處理器)

  
    誤區正確認知
  
  
    volatile 保證原子性volatile 僅保證可見性與有序性,i++ 非原子,需 AtomicInteger 或 synchronized
    final 對象不可變final 引用不可變,但對象內部可變狀態仍可修改,需深度不可變設計
    synchronized 只互斥synchronized 同時包含互斥、可見性 (hb)、有序性 (禁止重排)
    無鎖即無序正確同步 (volatile/final/lock) 即可獲得 JMM 保證的有序性
  


總結

JMM 是 Java 併發編程的基石契約。理解 happens-before 八大規則、volatile/final 語義增強、處理器模型差異與屏障插入,才能寫出正確、高性能的併發代碼。核心心法:先正確同步 (volatile/final/lock),再追求無鎖優化,切勿在未理解 JMM 前嘗試「聰明」的無鎖技巧。

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