CAS:比较并交换(compareAndSet)
CAS的全称是Compare-And-Swap,它是一条CPU并发原语。它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新值,这个过程是原子的。
我们先用一段代码来解释下什么叫:比较并交换
1、AtomicInteger atomicInteger = new AtomicInteger(10);//这是在堆内存里面创建一个atomicInteger对象,默认值为10。
2、System.out.println(atomicInteger.compareAndSet(10, 100)); //结果为true
3、System.out.println(atomicInteger.compareAndSet(10, 200)); //结果为false
4、System.out.println(atomicInteger); //结果为100
对于上面结果不明白的话,我们再来看下compareAndSet这个方法的源码:
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
参数1:expect期望值
参数2:update修改的值
当我们调用compareAndSet这个方法的时候,会先用expect期望值和atomicInteger对象的默认值进行对比,如果相等那么就用update的值去替换atomicInteger的默认值,如果不相等那么就不进行修改操作。 这就是我们说的先对比再修改。
我们看下具体代码实现:
我们再来解释下上面代码的意思:
1、创建一个原子对象atomicInteger默认值为10。
2、启动两个线程分别是AAA,和BBB都去修改atomicInteger的值。
3、线程AAA执行的时候先睡眠3秒钟,所以线程BBB先执行,线程BBB执行atomicInteger.compareAndSet(10, 1024);这行代码的时候,发现期望值是10和atomicInteger默认值一样也是10,所以执行修改操作,将1024赋值给atomicInteger,
4、线程AAA3秒睡眠结束后执行atomicInteger.compareAndSet(10, 2021);这行代码,发现期望值是10,atomicInteger的值已经是1024了,所以不能执行修改操作了。
5、所以最终atomicInteger的值是1024
当回答完上面的知识点后,面试官会认为你理解了CAS的百分之三十,面试官会继续问你CAS底层原理是什么? 我们继续回答:1、自旋锁。2、Unsafe类
1、Unsafe
1、是CAS的核心类,由于java无法直接访问底层系统,需要通过本地(native)来访问,Unsafe相当于一个后门,基于该类可以直接操作特定内存的数据,Unsafe类存在于sun.misc包中。其内部方法可以像C的指针一样直接操作内存。因为java中CAS操作依赖于Unsafe类的方法。
2、变量valueOffset,表示该变量值在内存中的偏移地址,应为Unsafe就是根据内存偏移地址获取值的。
3、CAS并发原语体现在JAVA语言中就是sun.misc.Unsafe类中的方法,调用Unsafe类中CAS方法,JVM会帮助我们实现出CAS汇编指令,这是一种完全依赖于硬件的功能,通过它实现了原子操作。再次强调CAS是一种系统原语,原语属于操作系统用语范畴,是由若干条指令组成的,用于完成某个功能的一个过程,原语的执行必须是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致问题。
以上代码解释
var1 AtomicInteger对象本身
var2 该对象值得引用地址
var4 需要改变的值
var5 是通过var1和var2找出的主内存中真实的值
用该对象当前的值于var5比较
如果相同,更新var5+var4并且返回true
如果不相同,继续取值,然后再比较,知道更新完成