基本概念
CAS算法是由硬件直接支持来保证原子性的。
CAS操作过程是一个原子操作,它是由一条CPU指令完成的。
有三个操作数:要更新的变量V、旧的预期值A和新值B。在要把变量更新时,现比较变量当前的值与旧的预期值A是否相同,相同就认为变量在这段时间没有发生变化,将B赋值给V,否则就什么都不做。
CAS的ABA问题
假若一个变量初次读取是A,在compare阶段依然是A,但其实可能在此过程中,它先被改为B,再被改回A,而CAS是无法意识到这个问题的。CAS只关注了比较前后的值是否改变,而无法清楚在此过程中变量的变更明细,这就是所谓的ABA漏洞。
解决:各种乐观锁的实现中通常都会用版本戳version(修改次数、版本号)来对记录或对象标记,避免并发操作带来的问题。
原子类的实现(AtomicInteger)
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
先检查当前value(偏移量为 valueOffset 的值)是否等于expect,如果相等,则意味着value没被其他线程修改过,则用update更新value的值并返回true。如果不相等,compareAndSet则会返回false,然后循环继续尝试更新。
compareAndSet调用了Unsafe类的compareAndSwapInt方法,compareAndSwapInt是个native方法,也就是平台相关的。
它是基于CPU的CAS指令来完成的。