CAS是什么?彻底搞懂CAS

CAS(Compare-And-Swap),它是一条CPU并发原语,用于判断内存中某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的。

CAS基本原理
CAS并发原语体现在Java中就是sun.misc.Unsafe类中的各个方法。调用UnSafe类中的CAS方法,JVM会帮我们实现CAS汇编指令。这是一套完全依赖于硬件的功能,通过它实现了原子操作。由于CAS是一种系统原语,原语属于操作系统用语,原语由若干指令组成,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被终端,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致的问题

unsafe类分析

如下是Unsafe类中的compareAndSwapInt,是一个本地方法,在unsafe.cpp中
CAS是什么?彻底搞懂CAS_第1张图片

CAS实现原子操作三大问题

CAS的ABA问题

CAS算法实现的一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并替换,那么在这个时间差类会导致数据的变化,比如线程M从内存位置W取出值A,这时N也取出A,N操作后A变成了B,然后N将B又变回A,这时线程M在CAS操作时发现内存中仍然是A,然后M执行成功,M虽然执行成功,但实际上就出现了ABA问题。

解决方案:Java1.5开始,JDK的Atomic包里提供了一个类AtomicStampedRefernce来解决ABA问题。这个类的compareAndSet方法的作用是首先检查当前引用是否等于预期引用,并且检查标志stamped是否为预期标志,如果全部一致,则继续。

CAS的循环时间长开销大问题

自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销,如果JVM能支持处理器提供的pause指令,那么效率会有一定的提升

pause指令的两个作用:

第一,它可以延迟流水线执行指令,使CPU不会消耗过多的执行资源

第二,它可以避免在退出循环的时候因内存顺序冲突而引起CPU流水线被清空

CAS的只能保证一个共享变量的原子操作问题

当对一个共享变量进行原子操作,循环CAS可以解决,但是如果是多个共享变量呢?循环CAS无法解决这个问题。

取巧的话就是合并共享变量:i=2,j=a -> ij=2a; 如此合并就可以操作了

解决方案:Java 5 开始,JDK提供了AtomicReference类来保证引用对象之间的原子性,就可以把多个变量放在一个对象进行CAS操作

你可能感兴趣的:(#,【Java高级】)