// 普通變量
int i1;
int getI1() { return i1; }
// volatile 變量
volatile int i2;
int getI2() { return i2; }
// synchronized 方法
int i3;
synchronized int getI3() { return i3; } // 語法錯誤,僅示意,實際應用於方法/代碼塊
JMM 模型:主內存 + 線程工作內存(寄存器、L1/L2 Cache)。
| 維度 | volatile | synchronized |
|---|---|---|
| 作用對象 | 變量 | 代碼塊/方法 |
| 核心保證 | 可見性 + 有序性 | 原子性 + 可見性 + 有序性 |
| 互斥性 | 無 | 有(互斥鎖) |
| 阻塞線程 | 不阻塞 | 會阻塞/等待 |
| 性能開銷 | 較低(內存屏障) | 較高(上下文切換、監視器操作) |
| 適用粒度 | 單個變量 | 多變量/復雜邏輯 |
| 死鎖風險 | 無 | 有(不當嵌套鎖) |
| JVM 優化 | 禁止重排序 | 鎖粗化、鎖消除、偏向鎖等 |
public class Singleton {
private volatile static Singleton instance; // 關鍵:禁止指令重排序
public static Singleton getInstance() {
if (instance == null) { // 第一次檢查
synchronized (Singleton.class) { // 加鎖
if (instance == null) { // 第二次檢查
instance = new Singleton(); // 非原子操作:分配內存→初始化→賦值
}
}
}
return instance;
}
}
無 `volatile` 時,`instance = new Singleton()` 可能重排序為:分配內存 → 賦值引用 → 初始化對象,導致其他線程看到「非 null 但未初始化完成」的對象。
public class Counter {
private int count = 0;
public synchronized void increment() { count++; } // 復合操作:讀-改-寫
public synchronized int getCount() { return count; }
}
`count++` 非原子,必須用 synchronized 或 `AtomicInteger` 保證原子性。
| 特性 | volatile | synchronized | final |
|---|---|---|---|
| 原子性 | ❌(長整型除外) | ✅ | ❌ |
| 可見性 | ✅ | ✅ | ✅(構造函數結束前) |
| 有序性 | ✅(禁止重排) | ✅(鎖語義) | ✅(構造函數內) |