1、含义
CAS(Compare And Swap)包含三个参数 CAS(V, E, N)
:
- V:表示要更新的变量;
- E:表示预期值;
- N:表示新值。
仅当 V 等于 E 时,才会将 E 更新为 N;如果 V 不等于 E,说明已经有其他线程更新了 V,则当前线程什么也不做。
以上操作表明 CAS 是无锁的,它总是抱着乐观态度,认为自己总是能完成操作。
2、实践
java.util.concurrent.atomic
包下的类,有一组用 CAS 实现的原子操作类。
以 AtomicInteger
为例:
public class AtomicInteger extends Number implements java.io.Serializable {
// setup to use Unsafe.compareAndSwapInt for updates
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);
}
}
private volatile int value;
public final int get() {return value;}
}
- Unsafe 是 CAS 的核心类,通过 Java 的 native 方法访问。
- 变量 value 用 volatile 修饰,保证了多线程环境下的可见性。
3、缺点
- ABA 问题 ``` 问题:如果变量V初次读取的时候是A,并且在准备赋值的时候检查到它仍然是A,那能说明它的值没有被其他线程修改过了吗?
如果在这段期间曾经被改成B,然后又改回A,那CAS操作就会误认为它从来没有被修改过。针对这种情况,java并发包中提供了一个带有标记的原子引用类AtomicStampedReference,它可以通过控制变量值的版本来保证CAS的正确性。 ```