CAS实现原子操作的三大问题

在java并发包中有一些并发框架也使用了自旋CAS的方式来实现原子操作,比如LinkedTransferQueue类的Xfer方法。CAS虽然很高效地解决了原子操作,但是CAS仍然存在三大问题ABA问题,循环时间长开销大,以及只能保证一个共享变量的原子操作。

ABA问题

在CAS操作值的时候,如果一个变量是A,变成了B,又变成了A,那么使用CAS进行检查时是发现没有变化,但是的确是变化了。解决思路加一个版本号去做标识,有点像线程里的信号量一样,在每次变量发生更新时是版本号+1,那么A–>B–>A 变成 1A->2B->3A,幸运的是咋java1.5开始,JDK的atomic包里里提供了AtomicStampedReference类来解决,这个类compareAndSet方法的作用是首先检查当前引用是否等于预期引用,并且检查当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设定为给定的更新值。

   /**
     * Atomically sets the value of both the reference and stamp
     * to the given update values if the
     * current reference is {@code ==} to the expected reference
     * and the current stamp is equal to the expected stamp.
     *
     * @param expectedReference the expected value of the reference
     * @param newReference the new value for the reference
     * @param expectedStamp the expected value of the stamp
     * @param newStamp the new value for the stamp
     * @return {@code true} if successful
     */
    public boolean compareAndSet(V   expectedReference,//预期引用
                                 V   newReference,//更新后引用
                                 int expectedStamp,//预期标志
                                 int newStamp) {//更新后标志
        Pair<V> current = pair;
        return
            expectedReference == current.reference &&
            expectedStamp == current.stamp &&
            ((newReference == current.reference &&
              newStamp == current.stamp) ||
             casPair(current, Pair.of(newReference, newStamp)));
    }

循环时间长开销大

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

  1. 延迟流水线执行指令de-pipline,使CPU不会消耗过多的执行资源,延迟的时间取决与具体实现的版本,在一些CPU上延迟时间是0
  2. 避免在退出循环的时候因内存顺序冲突引起CPU流水线清空,从而提高CPU执行效率。

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

当对一个共享变量执行操作时,我们可以使用循环cas(自旋锁)的方式保证原子性,但是对多个共享变量操作时,循环CAS就无法保证操作原子性,这时后可以取用锁,,也可以取巧把多个共享变量合并成一个共享变量操作。
从java1.5时,JDK提供了AtomicReference类保证引用对象之间的原子性。

长夜漫漫,代码做伴 加油!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值