volatile 確保變量對所有線程的可見性:一線程修改後,其他線程立即可見最新值。但不保證原子性(如 i++ 仍非原子)。
現代 CPU 多級緩存導致線程讀到舊值。以 i++ 為例,實際分三步:
多線程環境下,可能線程A讀取後未寫回,線程B讀到舊值,導致更新丟失。volatile 強制每次讀寫直接操作主存,禁用緩存優化。
32位系統下,long/double 佔64位,寫入需兩次32位操作。無 volatile 時,可能出現「高32位新、低32位舊」的數據撕裂。volatile 保證 64 位讀寫原子性。
volatile boolean shutdown = false; 線程輪詢退出volatile 修正單例模式指令重排// 錯誤:volatile 不保證 i++ 原子性
volatile int counter = 0;
public void increment() { counter++; } // 仍有競爭條件
// 正確:使用 AtomicInteger 或 synchronized
AtomicInteger counter = new AtomicInteger(0);
public void increment() { counter.incrementAndGet(); }
強烈推薦閱讀 IBM DeveloperWorks 經典文章:《Java 理論與實踐: 正確使用 Volatile 變量》,對 volatile 語義、內存屏障、JMM 模型有極深入闡述。