---
title: CAS 详解
description: CASæ¯è¾å¹¶äº¤æ¢æ·±åº¦è§£æï¼è¯¦è§£CASååæä½åçãUnsafeç±»å®ç°ãABAé®é¢åè§£å³æ¹æ¡ãèªæéæºå¶ã䏿²è§éæ§è½å¯¹æ¯ã
category: Java
tag:
- Javaå¹¶å
head:
- - meta
- name: keywords
content: CAS,Compare-And-Swap,ååæä½,ABAé®é¢,èªæé,ä¹è§é,Unsafe,CASåç
---
ä¹è§éåæ²è§éçä»ç»ä»¥åä¹è§é常è§å®ç°æ¹å¼å¯ä»¥é
读ç¬è
åçè¿ç¯æç« ï¼[ä¹è§éåæ²è§é详解](https://javaguide.cn/java/concurrent/optimistic-lock-and-pessimistic-lock.html)ã
è¿ç¯æç« 主è¦ä»ç» ï¼Java ä¸ CAS çå®ç°ä»¥å CAS åå¨çä¸äºé®é¢ã
## Java ä¸ CAS æ¯å¦ä½å®ç°çï¼
å¨ Java ä¸ï¼å®ç° CASï¼Compare-And-Swap, æ¯è¾å¹¶äº¤æ¢ï¼æä½çä¸ä¸ªå
³é®ç±»æ¯`Unsafe`ã
`Unsafe`ç±»ä½äº`sun.misc`å
ä¸ï¼æ¯ä¸ä¸ªæä¾ä½çº§å«ãä¸å®å
¨æä½çç±»ãç±äºå
¶å¼ºå¤§çåè½åæ½å¨çå±é©æ§ï¼å®é常ç¨äº JVM å
鍿ä¸äºéè¦æé«æ§è½ååºå±è®¿é®çåºä¸ï¼è䏿¨èæ®éå¼åè
å¨åºç¨ç¨åºä¸ä½¿ç¨ãå
³äº `Unsafe`ç±»ç详ç»ä»ç»ï¼å¯ä»¥é
读è¿ç¯æç« ï¼ð[Java éæ³ç±» Unsafe 详解](https://javaguide.cn/java/basis/unsafe.html)ã
`sun.misc`å
ä¸ç`Unsafe`ç±»æä¾äº`compareAndSwapObject`ã`compareAndSwapInt`ã`compareAndSwapLong`æ¹æ³æ¥å®ç°ç对`Object`ã`int`ã`long`ç±»åç CAS æä½ï¼
```java
/**
* 以å忹弿´æ°å¯¹è±¡å段çå¼ã
*
* @param o è¦æä½ç对象
* @param offset å¯¹è±¡åæ®µçå
ååç§»é
* @param expected ææçæ§å¼
* @param x è¦è®¾ç½®çæ°å¼
* @return 妿å¼è¢«æåæ´æ°ï¼åè¿å trueï¼å¦åè¿å false
*/
boolean compareAndSwapObject(Object o, long offset, Object expected, Object x);
/**
* 以å忹弿´æ° int ç±»åçå¯¹è±¡åæ®µçå¼ã
*/
boolean compareAndSwapInt(Object o, long offset, int expected, int x);
/**
* 以å忹弿´æ° long ç±»åçå¯¹è±¡åæ®µçå¼ã
*/
boolean compareAndSwapLong(Object o, long offset, long expected, long x);
```
`Unsafe`ç±»ä¸ç CAS æ¹æ³æ¯`native`æ¹æ³ã`native`å
³é®å表æè¿äºæ¹æ³æ¯ç¨æ¬å°ä»£ç ï¼éå¸¸æ¯ C æ C++ï¼å®ç°çï¼è䏿¯ç¨ Java å®ç°çãè¿äºæ¹æ³ç´æ¥è°ç¨åºå±ç硬件æä»¤æ¥å®ç°ååæä½ãä¹å°±æ¯è¯´ï¼Java è¯è¨å¹¶æ²¡æç´æ¥ç¨ Java å®ç° CASã
æ´åç¡®ç¹æ¥è¯´ï¼Java ä¸ CAS æ¯ C++ å
èæ±ç¼çå½¢å¼å®ç°çï¼éè¿ JNIï¼Java Native Interfaceï¼ è°ç¨ãå æ¤ï¼CAS çå
·ä½å®ç°ä¸æä½ç³»ç»ä»¥å CPU å¯åç¸å
³ã
`java.util.concurrent.atomic` å
æä¾äºä¸äºç¨äºååæä½çç±»ã

å
³äºè¿äº Atomic ååç±»çä»ç»å使ç¨ï¼å¯ä»¥é
读è¿ç¯æç« ï¼[Atomic ååç±»æ»ç»](https://javaguide.cn/java/concurrent/atomic-classes.html)ã
Atomic ç±»ä¾èµäº CAS ä¹è§éæ¥ä¿è¯å
¶æ¹æ³çååæ§ï¼èä¸éè¦ä½¿ç¨ä¼ ç»çéæºå¶ï¼å¦ `synchronized` åæ `ReentrantLock`ï¼ã
`AtomicInteger`æ¯ Java çååç±»ä¹ä¸ï¼ä¸»è¦ç¨äºå¯¹ `int` ç±»åçåéè¿è¡ååæä½ï¼å®å©ç¨`Unsafe`ç±»æä¾çä½çº§å«ååæä½æ¹æ³å®ç°æ éç线ç¨å®å
¨æ§ã
ä¸é¢ï¼æä»¬éè¿è§£è¯»`AtomicInteger`çæ ¸å¿æºç ï¼JDK1.8ï¼ï¼æ¥è¯´æ Java å¦ä½ä½¿ç¨`Unsafe`ç±»çæ¹æ³æ¥å®ç°ååæä½ã
`AtomicInteger`æ ¸å¿æºç å¦ä¸ï¼
```java
// è·å Unsafe å®ä¾
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
// è·åâvalueâåæ®µå¨AtomicIntegerç±»ä¸çå
ååç§»é
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// ç¡®ä¿âvalueâåæ®µçå¯è§æ§
private volatile int value;
// 妿å½åå¼çäºé¢æå¼ï¼åååå°å°å¼è®¾ç½®ä¸ºnewValue
// ä½¿ç¨ Unsafe#compareAndSwapInt æ¹æ³è¿è¡CASæä½
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
// ååå°å°å½åå¼å delta å¹¶è¿åæ§å¼
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
// ååå°å°å½åå¼å 1 å¹¶è¿åå ä¹åçå¼ï¼æ§å¼ï¼
// ä½¿ç¨ Unsafe#getAndAddInt æ¹æ³è¿è¡CASæä½ã
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
// ååå°å°å½åå¼å 1 å¹¶è¿ååä¹åçå¼ï¼æ§å¼ï¼
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
}
```
`Unsafe#getAndAddInt`æºç ï¼
```java
// ååå°è·åå¹¶å¢å æ´æ°å¼
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
// 以 volatile æ¹å¼è·å对象 o å¨å
ååç§»é offset å¤çæ´æ°å¼
v = getIntVolatile(o, offset);
} while (!compareAndSwapInt(o, offset, v, v + delta));
// è¿åæ§å¼
return v;
}
```
å¯ä»¥çå°ï¼`getAndAddInt` 使ç¨äº `do-while` 循ç¯ï¼å¨`compareAndSwapInt`æä½å¤±è´¥æ¶ï¼ä¼ä¸æéè¯ç´å°æåãä¹å°±æ¯è¯´ï¼`getAndAddInt`æ¹æ³ä¼éè¿ `compareAndSwapInt` æ¹æ³æ¥å°è¯æ´æ° `value` çå¼ï¼å¦ææ´æ°å¤±è´¥ï¼å½åå¼å¨æ¤æé´è¢«å
¶ä»çº¿ç¨ä¿®æ¹ï¼ï¼å®ä¼éæ°è·åå½åå¼å¹¶å次å°è¯æ´æ°ï¼ç´å°æä½æåã
ç±äº CAS æä½å¯è½ä¼å 为并åå²çªè失败ï¼å æ¤é常ä¼ä¸`while`å¾ªç¯æé
使ç¨ï¼å¨å¤±è´¥å䏿éè¯ï¼ç´å°æä½æåãè¿å°±æ¯ **èªæéæºå¶** ã
## CAS ç®æ³åå¨åªäºé®é¢ï¼
ABA é®é¢æ¯ CAS ç®æ³æå¸¸è§çé®é¢ã
### ABA é®é¢
妿ä¸ä¸ªåé V 忬¡è¯»åçæ¶åæ¯ A å¼ï¼å¹¶ä¸å¨åå¤èµå¼çæ¶åæ£æ¥å°å®ä»ç¶æ¯ A å¼ï¼é£æä»¬å°±è½è¯´æå®ç弿²¡æè¢«å
¶ä»çº¿ç¨ä¿®æ¹è¿äºåï¼å¾ææ¾æ¯ä¸è½çï¼å 为å¨è¿æ®µæ¶é´å®çå¼å¯è½è¢«æ¹ä¸ºå
¶ä»å¼ï¼ç¶ååæ¹å Aï¼é£ CAS æä½å°±ä¼è¯¯è®¤ä¸ºå®ä»æ¥æ²¡æè¢«ä¿®æ¹è¿ãè¿ä¸ªé®é¢è¢«ç§°ä¸º CAS æä½ç **"ABA"é®é¢ã**
ABA é®é¢çè§£å³æè·¯æ¯å¨åéåé¢è¿½å ä¸**çæ¬å·æè
æ¶é´æ³**ãJDK 1.5 以åç `AtomicStampedReference` 类就æ¯ç¨æ¥è§£å³ ABA é®é¢çï¼å
¶ä¸ç `compareAndSet()` æ¹æ³å°±æ¯é¦å
æ£æ¥å½åå¼ç¨æ¯å¦çäºé¢æå¼ç¨ï¼å¹¶ä¸å½åæ å¿æ¯å¦çäºé¢ææ å¿ï¼å¦æå
¨é¨ç¸çï¼å以ååæ¹å¼å°è¯¥å¼ç¨å该æ å¿çå¼è®¾ç½®ä¸ºç»å®çæ´æ°å¼ã
```java
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair