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     }
==========================================================================           如果您觉得这篇文章对你有帮助,可以【关注我】或者【点赞】,希望我们一起在架构的路上,并肩齐行
==========================================================================
原文地址:https://www.cnblogs.com/amberJava/p/12390939.html