Java总的CAS与ABA问题

CAS

cas全称是 Compare and swap 也就是比较-置换
是轻量级锁

  • 在我们程序执行的基本步骤是 取值—计算—赋值 三步,如何保证这三步的原子性是并发编程的基础。我们要实现并发程序的原子性就要保证在取值计算赋值操作时,不能有其他线程在同时修改,原子性的基本实现分为三步,例如AtomicInteger的递增计算
    • 第一步:取出旧值
    • 第二步:计算新值
    • 第三步:比较旧值与内存中的值是否相同,相同赋值,不同则自旋继续1.2.3的步骤
    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }

底层实现

CAS的方法基本集中在Unsafe中,内部的方法基本是使用native修饰。调用的方法是底层C++代码,在判断CPU核数>1后,返回lock指令,使用汇编语言的cmpxchgq调用不通的操作系统语言实现比较交换的原子性。lock cmpxchgq实现交换的原子性,会对内存加缓存行锁,如果内容超过64字节会添加总线锁
CAS是不走系统调用的,是在用户态的代码中“插入” cmpxchg 汇编指令,由这种CPU原语性质的汇编指令保证原子性。所以整体来看一直是在用户态代码中执行,而没有走入内核的代码。没有用户态/内核态之间的上下文切换。所以CAS的锁实现是轻量级的。

CAS实现的锁一定比重量级锁更加优异吗

不一定的

  • 大部分场景下CAS锁比切换到操作系统级别的锁更优(例如计算非常快的情况下,只有少数抢占锁冲突出现。
  • 如果在持有锁后需要进行长时间,大数据量的计算就适合重量级锁,让其他排队的线程进入队列挂起,释放持有的CPU资源,方便有需要的线程使用,避免计算资源的浪费。

ABA问题

  1. CAS是将旧值与新值比较的后相同再置换,但是存在一种情况,在置换的时候有其他线程修改了这个值,然后又恢复到原值,这时候原线程是不知道的,比较依然是没问题的,这就会出现ABA问题。在一般情况下不在乎值变迁情况的可以忽略,如果需要完全执行过程不有其他线程参与可以使用AtomicStraminteger,会通过版本记录的方式,对每次变更执行version+1操作。同时判断值相等和版本相同才精选置换。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值