CAS----Unsafe类----CAS底层思想----ABA问题----原子引用更新----ABA问题的规避
CAS(CompareAndSwap):比较并交换,是一条CPU并发原语
详述:判断内存某个位置的值是否为预期值,如果是则更新值,否则返回false,这个过程是原子的,底层靠UnSafe类来保证原子性;
并发原语体现在Unsafe中的各个方法,调用Unsafe类中的CAS方法,完全依赖于硬件的功能,通过它实现了原子操作
一般应用:循环判断预期值和主存中值直到相等(更新完成)
原语:由若干条指令组成,用于完成某个功能的一个过程,并且执行过程必须连续,不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成数据不一致性问题
过程描述:先比较(用期望值先和主内存中值进行比较,若结果为true(自己修改之前别人未修改),此时更新值 若比较返回false,则放弃修改 调用过程:用户程序----调用compareAndSet(原子类)----compareAndSwap***(Unsafe类)
AtomicInteger(原子整型类的成员方法实现) public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect,update); } //测试 public static void main(String[] args) { AtomicInteger f=new AtomicInteger(100); System.out.println(f.compareAndSet(100,99)+" "+f.get()); System.out.println(f.compareAndSet(100,101)+" "+f.get()); } 运行结果:true 99 false 99 分析:线程1和线程2同时从主存中拿到f(100),线程1首先将f更新为99,线程2此时发现值已被更新,则放弃更新f来源:JVM的rt运行jar包中, 描述:所有方法大部分都是native修饰的,调用操作系统的底层资源执行相应的任务),是CAS的核心类,Java对底层无能为力,需要通过本地native方法来访问,Unsafe相当于一个后门,基于Unsafe类的内部方法可以直接操作特定内存中的数据,因此Java中CAS操作的执行依赖于Unsafe中的方法
靠的是Unsafe类,因为Unsafe根据内存地址直接操作数据所以可保证原子性
synchronized:一致性得到保证,但是并发性下降 CAS:一致性、并发性得到保证
不足之处: 1、若CAS失败,则会一直尝试,CPU开销很大 2、当对一个共享变量执行操作时,可使用循环CAS的方式来保证原子操作,有多个共享变量需考虑加锁 3、引出ABA问题
ABA问题: CAS算法实现的重要前提是取出内存中某时刻的数据并在当下时刻 比较并交换,那么在这个 时间差 内数据可能会发生 多次变化 情景举例: 线程1从内存中取出A,这时候线程2也从内存中取出A,并且线程2进行了一些操作将值变成了B,然后线程2又将值改回了A,这时候线程1进行CAS操作发现内存中依然是A,然后线程1操作成功
原子引用+版本号机制(类似于时间戳) jdk实现的带时间戳的原子引用AtomicStampedReference,在每次更新时要判断期望值和版本号两者是否都未发生变化