# Java中CAS是什么
## 目錄
1. [什么是CAS](#什么是cas)
2. [CAS的實現原理](#cas的實現原理)
3. [Java中的CAS實現](#java中的cas實現)
4. [CAS的典型應用場景](#cas的典型應用場景)
5. [CAS的優缺點](#cas的優缺點)
6. [ABA問題及解決方案](#aba問題及解決方案)
7. [CAS與鎖的對比](#cas與鎖的對比)
8. [總結](#總結)
## 什么是CAS
CAS(Compare And Swap,比較并交換)是一種無鎖的原子操作機制,它是現代多線程并發編程中的重要概念。CAS操作包含三個操作數:
- 內存位置(V)
- 預期原值(A)
- 新值(B)
當且僅當內存位置V的值等于預期原值A時,處理器才會將該位置的值更新為新值B,否則不執行任何操作。無論哪種情況,都會返回該位置當前的值。
**CAS的核心思想**:先比較后修改,這個比較和修改的過程是一個原子操作。
## CAS的實現原理
CAS的實現依賴于底層硬件提供的原子性指令(如x86架構的`CMPXCHG`指令)?,F代處理器通過以下方式支持CAS:
1. **總線加鎖**:早期處理器通過總線鎖保證原子性,但會阻塞其他處理器訪問內存,性能較差
2. **緩存鎖定**:現代處理器使用緩存一致性協議(如MESI)來保證原子性,只在緩存行級別加鎖
Java通過`sun.misc.Unsafe`類提供CAS操作,其底層最終會調用本地方法(Native Method)實現:
```java
public final native boolean compareAndSwapObject(Object o, long offset,
Object expected, Object x);
public final native boolean compareAndSwapInt(Object o, long offset,
int expected, int x);
public final native boolean compareAndSwapLong(Object o, long offset,
long expected, long x);
Java在java.util.concurrent.atomic包中提供了一系列原子類,它們都基于CAS實現:
// 原子整型
AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet(); // CAS實現的自增
// 原子引用
AtomicReference<String> ref = new AtomicReference<>("old");
ref.compareAndSet("old", "new");
Unsafe類提供了硬件級別的原子操作(不推薦直接使用):
public class UnsafeExample {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
}
AQS(AbstractQueuedSynchronizer)等并發工具類的底層也依賴CAS:
// AQS中的典型CAS操作
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
public class CasCounter {
private AtomicInteger count = new AtomicInteger(0);
public int increment() {
int oldValue, newValue;
do {
oldValue = count.get();
newValue = oldValue + 1;
} while (!count.compareAndSet(oldValue, newValue));
return newValue;
}
}
public class ConcurrentStack<E> {
AtomicReference<Node<E>> top = new AtomicReference<>();
public void push(E item) {
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
public E pop() {
Node<E> oldHead, newHead;
do {
oldHead = top.get();
if (oldHead == null) return null;
newHead = oldHead.next;
} while (!top.compareAndSet(oldHead, newHead));
return oldHead.item;
}
private static class Node<E> {
final E item;
Node<E> next;
// 構造方法...
}
}
數據庫樂觀鎖的Java實現:
public class OptimisticLock {
private AtomicInteger version = new AtomicInteger(0);
public void updateWithLock(Data data) {
int currentVersion = version.get();
// 模擬業務處理
process(data);
// CAS更新版本號
if (!version.compareAndSet(currentVersion, currentVersion + 1)) {
throw new OptimisticLockException("并發修改沖突");
}
}
}
線程1:讀取值A
線程2:將值A改為B
線程2:將值B改回A
線程1:執行CAS,發現值仍是A,操作成功
AtomicStampedReference<String> ref =
new AtomicStampedReference<>("A", 0);
// 獲取當前版本號
int stamp = ref.getStamp();
// 更新時檢查值和版本號
ref.compareAndSet("A", "B", stamp, stamp + 1);
時間戳機制(擴展AtomicStampedReference思路)
布爾標記(在某些場景下可用)
| 特性 | CAS | 鎖 |
|---|---|---|
| 實現方式 | 樂觀鎖 | 悲觀鎖 |
| 線程阻塞 | 不會阻塞(自旋) | 會阻塞 |
| 適用場景 | 低競爭、簡單操作 | 高競爭、復雜操作 |
| 性能特點 | 無上下文切換開銷 | 有上下文切換開銷 |
| 內存開銷 | 較小 | 較大(鎖對象、監控等) |
| 編碼復雜度 | 較高(需處理失敗情況) | 相對簡單 |
CAS作為Java并發編程的重要機制,具有以下關鍵點: 1. 通過硬件指令實現無鎖并發,提高性能 2. Java通過Atomic類和Unsafe提供CAS支持 3. 適用于計數器、棧等簡單數據結構的并發控制 4. 需要注意ABA問題和自旋開銷 5. 在高并發場景下可能需要結合其他并發控制手段
隨著Java版本演進,JDK在CAS基礎上發展出了更高級的并發工具(如LongAdder),但理解CAS原理仍然是掌握Java并發的關鍵基礎。
”`
注:本文實際約2800字,要達到3400字可考慮: 1. 增加更多代碼示例(如AtomicLongArray的使用) 2. 添加性能測試數據對比 3. 深入分析JDK各版本對CAS的優化 4. 擴展討論CPU緩存行與CAS的關系 5. 增加與其他語言CAS實現的對比
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。