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

Java volatile 關鍵字深度解析:可見性、有序性與禁止指令重排

     編輯:Java 程式設計入門

核心語義:兩大保證

  1. 可見性:寫入 volatile 變量的值,對其他線程立即可見。實現:寫入時刷新到主內存,讀取時從主內存加載(繞過 CPU 緩存)。
  2. 有序性 (禁止指令重排):volatile 讀寫前後的指令不會被重排序(JMM Happens-Before 規則)。

不保證原子性:volatile int i; i++; 仍非原子(讀-改-寫三步),需配合 AtomicInteger 或 synchronized。

Java 內存模型 (JMM) 背景

  • 線程私有工作內存(緩存、寄存器)存儲共享變量副本。
  • 無同步時,編譯器/CPU/運行時可重排指令、緩存延遲寫入,導致可見性問題、有序性違背。
  • volatile 插入內存屏障:
// 寫屏障:StoreStore + StoreLoad
volatileVar = value; // 確保之前寫入不被重排到此後,且立即刷新主存

// 讀屏障:LoadLoad + LoadLoad
x = volatileVar; // 確保此讀不被重排到之前,且從主存讀取最新值

經典雙重檢查鎖單例 (DCL) —— volatile 必不可少

public class Singleton {
    private volatile static Singleton instance; // 禁止指令重排:分配內存 -> 初始化 -> 賦值引用
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) { // 第一次檢查(無鎖,性能)
            synchronized (Singleton.class) {
                if (instance == null) { // 第二次檢查
                    instance = new Singleton(); // 非原子:1.分配 2.初始化 3.賦值
                }
            }
        }
        return instance;
    }
}

無 volatile 時,步驟 2/3 可能重排,導致其他線程看到半初始化對象。

volatile 適用場景與局限

場景是否適合說明
狀態標誌位✅ 完美volatile boolean running、volatile boolean shutdown
單次發布 (Safe Publication)✅ 適合對象構造完成後發布引用,配合 final 字段保證不可變對象安全發布
獨立觀察 (One Writer, Many Readers)✅ 適合配置熱更新、計數器快照讀(寫入用 CAS/鎖)
複合操作 (i++, check-then-act)❌ 不適合需 Atomic* / synchronized / Lock
多變量不變式關聯❌ 不適合需鎖保證多變量原子性

volatile vs synchronized

  • volatile:輕量級,無阻塞,僅保證可見性+有序性,適用單變量。
  • synchronized:重量級(早期),可重入,保證原子性+可見性+有序性,適用臨界區/多變量。
  • JDK 6+ 鎖優化(偏向鎖、輕量級鎖、鎖消除、鎖粗化)大幅縮小性能差距。

實戰模式:volatile + CAS 實現無鎖計數器

public class CasCounter {
    private volatile int value; // 可見性
    public int increment() {
        int prev, next;
        do {
            prev = value;
            next = prev + 1;
        } while (!UNSAFE.compareAndSwapInt(this, VALUE_OFFSET, prev, next)); // 原子性
        return next;
    }
}

實際開發直接用 AtomicInteger 或 LongAdder。

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