☕ Java 原子性變數與 CAS 筆記
📌 一、什麼是「原子性變數」與 CAS?
在多執行緒環境下,多個執行緒若同時修改同一個變數,容易發生資料競爭。
Java 提供 java.util.concurrent.atomic
套件,裡面有許多「原子操作」的變數類型,例如:
AtomicInteger
AtomicLong
AtomicReference
這些類別提供 非阻塞(non-blocking) 的操作方式,底層就是使用 CAS(Compare-And-Swap,比較並交換) 實作的。
⚙️ 二、CAS 的核心邏輯
CAS 是一種樂觀鎖策略,基本流程如下:
- 讀取目前值
- 比對是否與預期值一致
- 若一致,就更新為新值
- 若不一致,就放棄(重試或結束)
✅ 優點:不用 synchronized 就能寫出安全的多執行緒操作
❌ 缺點:高併發時可能需要一直 retry,自旋過多會浪費 CPU
💡 三、實際範例:用 CAS 實作「無鎖計數器」
1 | import java.util.concurrent.atomic.AtomicInteger; |
🔍 這裡的 compareAndSet(old, new)
就是 CAS 的操作:
如果 counter
的值還是等於 old
,就設為 new
,否則什麼都不做。
🚧 四、CAS 的常見問題與限制
問題類型 | 說明 |
---|---|
ABA 問題 | 值從 A ➝ B ➝ A,CAS 會誤判沒變。可用 AtomicStampedReference 解決。 |
自旋太久 | 高併發下 CAS 一直失敗,浪費 CPU(spin loop) |
無法批次更新 | 只能針對單一變數操作,無法同時修改多個變數 |
📚 補充用法(其他類型)
1 | AtomicLong longValue = new AtomicLong(100); |
本部落格所有文章除特別聲明外,均採用CC BY-NC-SA 4.0 授權協議。轉載請註明來源 Cheng's Tech & Life!