• CAS中的ABA问题


    经典的ABA问题:

     ABA问题存在CAS无锁方案中,我们写一个CAS的伪代码栗子:

    class SimulatedCAS{
        volatile int    count;
        int newValue;
        //实count+=1
        addOne(){
             do    {
                  newValue=count+1;    //
            }while(count != cas(count,newValue)    )//
        }
        //模拟实现CAS,仅⽤来帮助理解
        synchronized int cas( int expect, int newValue){
            // 读⽬前count的值
            int    curValue=count;
            //    ⽐较⽬前count值是否==期望值
            if(curValue==expect){
            //    如果是,则更新count的值
                count=newValue;
            }
            //    返回写⼊前的值
            return    curValue;
        }
    
    }
    假设 count原本是 A,线程 T1 在执行完代码①处之后,执行代码②处之前,有可能 count 被线程 T2 更新成了 B,之后又被 T3 更新回了 A,这样线程 T1 虽然看到的一直是 A,但是这个值其实已经被其他线程更新过了,这就是 ABA 问题
     

    如何解决:

    最简单的方案就是给值加一个修改版本号,每次值变化,都会修改它版本号,CAS操作时都对比此版本号。

    Java中提供的原子化的对象引用类型AtomicStampedReferenceAtomicMarkableReference 这两个原子类可以解决 ABA 问题。
     
     1     public boolean compareAndSet(V   expectedReference, V   newReference,
     2                                  int expectedStamp, int newStamp) {
     3         Pair<V> current = pair; //获取当前pair
     4         return
     5                 expectedReference == current.reference && //原始值等于当前pair的值引用,说明值未变化
     6                 expectedStamp == current.stamp && // 原始标记版本等于当前pair的标记版本,说明标记未变化
     7                         
     8                 ((newReference == current.reference && newStamp == current.stamp) || // 将要更新的值和标记都没有变化
     9                         casPair(current, Pair.of(newReference, newStamp))); // cas 更新pair
    10     }
    ==========================================================================           如果您觉得这篇文章对你有帮助,可以【关注我】或者【点赞】,希望我们一起在架构的路上,并肩齐行
    ==========================================================================
  • 相关阅读:
    一个简单的反反爬~
    查缺补漏 -- python 之 and or的优先级
    从今天开始看《Redis深度历险》--HyperLogLog
    从今天开始看《Redis深度历险》--位图
    从今天开始看《Redis深度历险》--延时队列
    从今天开始看《Redis深度历险》--分布式锁
    redis之set【官方文档搬运+翻译】
    从今天开始看《Redis深度历险》--基础
    collections模块学习之namedtuple
    元组赋值谜题
  • 原文地址:https://www.cnblogs.com/amberJava/p/12390939.html
Copyright © 2020-2023  润新知