volatile 被譽為「輕量級的 synchronized」,但**僅保證可見性,不保證原子性**。濫用會導致並發 Bug,必須精準把握適用場景。
volatile 變量與普通變量的讀寫順序不被 JVM/CPU 優化打亂。i++、flag = !flag 等複合操作,**即使加 volatile 仍不安全**。
// 錯誤示範:檢查-設置非原子
private volatile boolean flag;
if (!flag) { flag = true; } // 多線程下可能多次進入
synchronized 實現「讀寫分離」:public class AnotherSyncSample {
private volatile int counter; // 讀取無鎖,極快
public int getCounter() { return counter; }
public synchronized void add() { counter++; } // 寫入加鎖保證原子性
}
class VolatileSample {
private volatile boolean finished;
private int lucky;
public void doSomething() {
if (finished) System.out.println("lucky: " + lucky); // 讀到 finished=true 時,lucky 必為 7
}
public void finish() {
lucky = 7;
finished = true; // volatile 禁止 lucky=7 後於 finished=true 重排
}
}
無 volatile 時,JVM 可能先寫 finished=true 再寫 lucky=7,導致另一線程讀到 finished=true 但 lucky=0。
volatile 適合**狀態標記**、**一次性發布**、**獨立觀察**場景。synchronized、Lock 或 atomic。