synchronized 鎖覆蓋範圍可大可小(方法級、塊級),上下文切換、內存屏障開銷較大。volatile 僅作用於單個變量,無鎖、無阻塞,同步開銷極低,適合「讀多寫少」、「狀態標誌」、「單次寫入可見性」場景。
happens-before 關係。不保證原子性:i++(讀-改-寫)非原子,多線程下仍會丟失更新。
LOCK 前綴指令、MESI 緩存一致性協議強制緩存行失效/回寫。public class TestRaceCondition {
private volatile int i = 0;
public void increase() { i++; } // 非原子!
public int getValue() { return i; }
}
100 線程各調用 100 次 increase(),期望 10000,實際往往 < 10000。原因:i++ 展開為 read → add → write,中間窗口期其他線程寫入會被覆蓋。
三元操作數:內存位置 V、預期舊值 A、新值 B。
原子語義:若 V == A 則 V = B 並返回 true,否則不修改並返回 V 當前值。
硬件支援:
cmpxchg 指令族lwarx/stwcx (Load-Reserved/Store-Conditional)ll/sc (Load-Linked/Store-Conditional)線程失敗/掛起不影響其他線程,避免鎖帶來的優先級反轉、死鎖、上下文切換開銷。
public final int getAndSet(int newValue) {
for (;;) { // 自旋重試
int current = get();
if (compareAndSet(current, newValue)) return current;
}
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
Unsafe 類封裝 Native CAS 操作。valueOffset 為字段在對象內存偏移量,經 objectFieldOffset 獲取。getAndIncrement、getAndDecrement、getAndAdd 等。| 原子類 | 適用類型 | 備註 |
|---|---|---|
| AtomicInteger / AtomicLong | int / long | 基礎數值運算 |
| AtomicReference | 任意對象引用 | 含 Double/Float 包裝類,但不支援浮點運算 |
| AtomicIntegerArray / AtomicLongArray | 數組元素 | 細粒度數組元素原子更新 |
| AtomicStampedReference | 帶版本戳引用 | 解決 ABA 問題 |
線程 1 讀取 V=A,線程 2 將 V 改為 B 再改回 A,線程 1 執行 CAS 判斷 V==A 成功,實際上狀態已發生變化。對於「引用指向對象內容已變」敏感場景(如無鎖棧節點復用)會導致邏輯錯誤。
volatile boolean shutdown、volatile int state) → volatile 最簡潔高效。AtomicLong/Integer 無鎖高吞吐。synchronized 或 Lock 保證原子性。ConcurrentLinkedQueue、ConcurrentHashMap (JDK 8+) 實現模式。volatile 提供輕量級可見性與有序性保證,CAS 賦予硬件級原子更新能力,二者構成 Java 高性能併發編程的雙基石。理解 JMM 語義、處理器內存模型、ABA 邏輯漏洞,方能在無鎖編程中遊刃有餘,構建可伸縮、高吞吐的多核應用。