CAS的全称为Compare-And-Swap,它是一条CPU并发原语
它的功能是判断内存某个位置的值是否为预期值,如果是则改为新的值,这个过程是原子的。
CAS并发原语体现在Java语言中就是sun.misc.Unsafe类中的各个方法。
调用Unsafe类中的CAS方法,JVM会帮我们实现出CAS汇编指令。这是一种完全依赖于硬件的功能。
由于CAS是一种系统原语,原语属于操作系统用语范畴,是由若干条指令组成的,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致问题。
比较当前工作内存中的值和主内存中的值,如果相同则执行规定操作,否则继续比较直到主内存和工做内存中的值一直(自旋)
CAS有三个操作数,内存值V,预期值A,要更新的值B,如果V==A,则V=B,否则什么都不做。
JUC包-java.util.concurrent 中 AtomicInteger类
示例代码如下:
private static final Unsafe U = Unsafe.getUnsafe();
/**
* 获取当前值并+1
* Atomically increments the current value,
* with memory effects as specified by {@link VarHandle#getAndAdd}.
*
* Equivalent to {@code getAndAdd(1)}.
*
* @return the previous value
*/
public final int getAndIncrement() {
return U.getAndAddInt(this, VALUE, 1);
}
/**
* Atomically adds the given value to the current value of a field
* or array element within the given object {@code o}
* at the given {@code offset}.
*
* @param o object/array to update the field/element in
* @param offset field/element offset
* @param delta the value to add
* @return the previous value
* @since 1.8
*/
//o为当前对象,offset为内存地址偏移量,delta需要增加的值
@HotSpotIntrinsicCandidate
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
//获取当前对象在offset偏移量上的值
v = getIntVolatile(o, offset);
} while (
!weakCompareAndSetInt(o, offset, v, v + delta));
return v;
}
@HotSpotIntrinsicCandidate
public final boolean weakCompareAndSetInt(Object o, long offset,int expected, int x) {
//如果当前对象,内存地址偏移量offset上的值为excepted, 则将该值替换为x
return compareAndSetInt(o, offset, expected, x);
}
Unsafe底层源码
CAS缺点
1、循环时间长,系统开销大
do-while
2、只能保证一个共享变量的原子操作
3、CAS会产生ABA问题
ABA问题?一个线程T1从内存位置V中取出值A,一个线程T2从内存位置V中取出值也是A,T1使用CAS算法 将A改为B,
然后又使用CAS算法将B改为A,然后T2使用CAS算法将A改为C
虽然T2操作成功,但并不代表整个过程是没有问题的。
1、修改版本号(时间戳)
示例:AtomicStampReference