在並發編程領域,線程間的通信與同步是兩大核心課題。Java 採用共享內存模型,但線程通信對程序員透明,這便引出了記憶體可見性問題。本文系統梳理 Java 記憶體模型(JMM)、指令重排序規則、happens-before 原則及 as-if-serial 語義,助你構建堅實的並發理論基石。
在命令式編程中,線程通信主要有兩種方式:
Java 採用共享內存模型,但將通信細節封裝於 JMM 內部,對開發者透明。若不理解其底層機制,極易遭遇可見性、原子性、有序性問題。
JMM 定義線程與主內存的抽象關係:
線程 A 與 B 通信需經兩步:
1. 線程 A 將本地內存更新的共享變量刷新至主內存。
2. 線程 B 從主內存讀取線程 A 更新後的值。
JMM 通過控制主內存與本地內存交互,提供記憶體可見性保證。
為提升性能,編譯器與處理器會對指令重排序:
其中 (1) 屬編譯器重排序,(2)(3) 屬處理器重排序。JMM 通過禁止特定編譯器重排序、插入內存屏障指令來約束處理器重排序。常見 x86 僅允許 Store-Load 重排序,ARM 架構則更寬鬆(可能支援 Load-Load、Load-Store、Store-Store)。
JSR-133 引入 happens-before 概念,用於描述操作間的記憶體可見性。核心規則包括:
happens-before 本質是展示給程序員理解 JMM 底層重排序的一組規則,保證「前一個操作的結果對後一個操作可見」。
as-if-serial 語義保證:無論如何重排序,單線程程序執行結果不可改變。編譯器、運行時與處理器需共同遵守,為單線程開發者屏蔽重排序複雜性。
掌握 JMM 抽象結構、重排序分類與應對、happens-before 規則體系,是編寫正確、高效並發程序的前提。下一步可深入探討鎖機制、原子類、並發容器等進階主題。