CAS是什么?CompareAndSwap(比较再交换)

CAS是什么?

CAS ==> CompareAndSwap ==> 比较再交换

public static void main(String[] args){
	AtomicInteger atomicInteger = new AtomicInteger(5);
	//main do thing
	System.out.println(atomicInteger.compareAndSet(5,2019)+"\t current data:"+atomicInteger.get());
	System.out.println(atomicInteger.compareAndSet(5,1024)+"\t current data:"+atomicInteger.get());
}

在这里插入图片描述
当主物理内存中的值,和传入的第一个值一样时,返回true(比较),则更新物理内存中的值为传入的第二个值(交换)。

当主物理内存中的值,和传入的第一个值不同时,返回false(比较),则本次修改失败。需要重新获得物理内存中的真实值。

CAS(CompareAndSwap),是一条CPU并发原语
它的功能是判断内存某个位置的值,是否为预期值,如果是则更新为新的值,这个过程是原子的。

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

假设线程A和线程B两个线程同时执行getAndAddInt操作(分别跑在不同CPU上):

  1. AtomicInteger里面的value原始值为3,即主内存中AtomicInteger的value为3,根据JMM模型,线程A和线程B各自持有一份值为3的value的副本,分别到各自的工作内存。
  2. 线程A通过getIntVolatile(var1, var2)拿到value值3,这时线程A被挂起。
  3. 线程B也通过getIntVolatile(var1, var2)方法获取到value值3,此时刚好线程B没有被挂起,并执行compareAndSwapInt方法,比较内存值也为3,成功修改内存值为4,线程B打完收工,一切OK
  4. 这时线程A恢复,执行compareAndSwapInt方法比较,发现自己手里的值数字3和主内存的值数字4不一致,说明该值已被其他线程抢先一步修改过了,那A线程本次修改失败,只能重新读取重新来一遍了
  5. 线程A重新获取value值,因为变量value被volatile修饰,所以其他线程对它的修改,线程A总是能够看到,线程A继续执行compareAndSwapInt进行比较替换,直到成功。

CAS应用:
CAS有三个操作数,内存值V,旧的预期值A,要修改的更新值B。
当且仅当与气质A和内存值V相同时,将内存值V修改为B,否则什么都不做。

在这里插入图片描述

CAS缺点:

  1. 循环时间长开销很大(CAS失败会一直尝试,若长时间不成功,会给CPU带来很大开销)在这里插入图片描述

  2. 只能保证一个共享变量的原子操作
    当对一个共享变量执行操作时,我们可以使用循环CAS的方式来保证原子操作,
    但是,对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候就可以用锁来保证原子性。

  3. 引出ABA问题。
    CAS——>UnSafe——>CAS底层思想——>ABA——>原子引用更新——>如何规避ABA问题

ABA问题:
假设有两个线程A和B,A线程完成工作慢,假设为10s,B完成较快,假设为2S,假设两个线程均要操作目标值X=10,A将目标值X取回自己工作内存中,开始工作,B在A工作期间,将X修改为’998’,又在A完成工作前,把X改回’10’,等A完成工作,把自己工作内存中的X和内存中当前的X进行比较,结果一致,则误以为自己工作期间,无人操作过X。此上即为ABA问题,

PS:感谢尚硅谷周阳老师

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值