一、什么是CAS
CAS即Compare And Swap。
CAS主要用在并发领域,用来实现不可被打断的数据交换操作。
CAS有三个操作数:内存值V、预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,才将内存值修改为B,否则什么都不做。最后返回现在的V值。
使用代码模拟:
public class SimulatedCAS{
private volatile int value;
//使用synchronized来保证原子性
public synchronized int compareAndSwap(int expectedValue,int newValue){
int oldValue = value;
if(oldValue == expectedValue){
value = newValue;
}
return value;
}
}
二、CAS的应用场景
- 乐观锁
- 并发容器(ConcurrentHashMap)
- 原子类
三、原子类使用CAS
- AtomicInteger加载Unsafe工具,用来直接操作内存数据;
- 用volatile修饰value字段保证可见性。
1.源码分析
以getAndAdd(int delta)
方法为例,通过源码分析:
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
在其中会调用unsafe的getAndAddInt
方法:
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
从源码可以看到,在CAS操作失败后,会一直进行自旋,重复着do while中的代码。getIntVolatile和compareAndSwapInt都是native方法。
2.Unsafe类
因为Java无法直接访问底层操作系统,而是通过native方法来访问。不过尽管如此,JVM还提供一个后门叫Unsafe,它提供了硬件级别的原子操作。
valueOffset表示的就是变量值在内存中的偏移地址,因为Unsafe就是根据内存偏移地址获取数据的原值的,这样我们就能通过Unsafe来实现CAS了。
四、CAS的缺点
1.ABA问题
可以通过版本号、时间戳来解决。