CAS/ABA

作者: TUCJVXCB | 来源:发表于2019-08-10 22:37 被阅读0次

    CAS:CompareAndSwap,是一种原子操作,用于在多线程环境中保证不被打断的数据交换操作,用旧值和主内存中的值做比较,如果相同则讲旧值替换成新值,Java中由sun.misc.UnSafe类实现CAS。


    AtomicInteger这个类在多线程环境下是线程安全的,它的getAndIncrement()方法能够在多线程环境下安全地实现i++操作,以下是它的源码,它调用了UnSafe类的getAndAddInt方法。

        public final int getAndIncrement() {
            return unsafe.getAndAddInt(this, valueOffset, 1);
        }
    
        public final int getAndAddInt(Object var1, long var2, int var4) {
            int var5;//定义一个新值
            do {
                var5 = this.getIntVolatile(var1, var2);//将val1对象在var2内存地址的值赋给var5
            } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));//这里的compareAndSwapInt方法是将var1对象在var2内存地址的值和var5比较,如果相同的话,var5设置为var5+var4,并且这个返回返回true,跳出循环。如果旧值var5和内存中的值不相同的话,则在while中一直循环,直至值相同为止
    
            return var5;
        }
    

    CAS的缺点:

    • 如果旧值和内存中的值一直不相等,会一直循环,会给CPU带来很大的开销
    • CAS只能对一个共享变量保证原子操作,无法对多个共享变量保证原子操作
    • ABA问题

    ABA

    什么是ABA?假设有两个线程,分别叫T1和T2,T1和T2分别从主内存中拷贝一份变量,这个变量的值是A,T1和T2线程都要对变量A修改操作,T2先作出修改,根据CAS原则,变量A在主内存中的值还是A,所以A被修改成为B,紧接着T2线程又对B进行修改,把B改成A,T2线程完成任务,被挂起。然后T1线程修改变量的值,工作内存的值和主内存的值都是A,所以T1线程也可以修改这个变量,但是T1线程不知道该变量在它修改之前已经被修改过了。

    那么如何解决ABA问题?

    使用J.U.C包提供的AtomicStampedReference类,用版本号来控制CAS。

    相关文章

      网友评论

          本文标题:CAS/ABA

          本文链接:https://www.haomeiwen.com/subject/zxydjctx.html