Java 兩大內建同步機制:**`synchronized` (鎖/監視器)** 與 **`volatile` (變數)**。`volatile` 提供 **可見性** (寫入對後續讀取立即可見)、**有序性** (禁止指令重排序),**不提供原子性** (複合操作如 `i++` 非原子)。**開銷遠低於鎖**:讀幾乎無損耗,寫僅需記憶體屏障。**不阻塞線程**,擴展性優於鎖。
**違反任一條件 → 必須用 `synchronized` / `Lock` / 原子類 (`AtomicInteger` 等) / `StampedLock`。`volatile` 無法替代。
volatile boolean shutdownRequested;
public void shutdown() { shutdownRequested = true; }
public void doWork() {
while (!shutdownRequested) { /* do stuff */ }
}
public class BackgroundLoader {
public volatile HeavyObject heavy; // 唯一寫入點
public void init() {
heavy = new HeavyObject(); // 構建完成後單次發布
}
}
public class Consumer {
public void use(BackgroundLoader loader) {
if (loader.heavy != null) { // volatile 讀取保證可見性
loader.heavy.doSomething(); // 物件必須線程安全或有效不可變
}
}
}
public class SensorReader {
public volatile TemperatureSnapshot latest; // 定期更新
public void run() {
while (running) {
latest = new TemperatureSnapshot(readSensor()); // 不可變快照
sleep(1000);
}
}
}
@ThreadSafe
public class Person {
private volatile String firstName;
private volatile String lastName;
private volatile int age;
// 純 getter/setter,無邏輯
public String getFirstName() { return firstName; }
public void setFirstName(String fn) { this.firstName = fn; }
// ...
}
@ThreadSafe
public class CheesyCounter {
@GuardedBy("this") private volatile int value; // 寫用鎖,讀用 volatile
public int getValue() { return value; } // volatile 讀,無鎖
public synchronized int increment() { // 寫加鎖保證原子性
return value++;
}
}
| 維度 | volatile | synchronized | AtomicInteger / LongAdder |
|---|---|---|---|
| 讀開銷 | 極低 (≈ 普通讀 + LoadLoad 屏障) | 低 (無競爭鎖獲取 ~幾十 ns) | 極低 (CAS/LongAdder 分段) |
| 寫開銷 | 中 (StoreStore + StoreLoad 屏障) | 中 (鎖釋放屏障) | 中高 (CAS 重試 / LongAdder 低競爭極低) |
| 阻塞 | 無 | 有 (競爭時) | 無 (CAS 自旋) / 無 |
| 擴展性 | 極佳 (讀無競爭) | 受限 (鎖競爭) | 極佳 (LongAdder 高併發最優) |
| 適用場景 | 單一變數、條件滿足的模式 | 複雜臨界區、多變數不變式 | 計數器、累加器、高併發統計 |
**結論**:能用 `LongAdder`/`Atomic*` 解決計數/統計,**優先用它們**。`volatile` 保留給「單一引用/標誌/快照發布」等**語義單純、條件嚴格匹配**的場景。
volatile int[] arr:`volatile` 修飾**引用**,不保護**陣列元素**。`arr[0]=1` 無可見性保證 → 用 `AtomicIntegerArray` / `copyOf` 新陣列發布。volatile List list:同理,列表結構變更 (add/remove) 無保護 → 用 `Collections.unmodifiableList` 發布新實例 / `CopyOnWriteArrayList`。`volatile` 是**精準手術刀**,而非「萬能鎖」。**嚴格遵守兩大前提條件**,套用五大經典模式,**配合 `final`、不可變物件、原子類**,能在讀多寫少、狀態發布、標誌控制等場景實現**無鎖、高擴展、低延遲**的同步。濫用或誤用,將引入極難復現的並發 Bug。**尊重 JMM,敬畏並發**。