ABA问题及解决办法

一个线程把数据A变为了B,然后又重新变成了A。此时另外一个线程读取的时候,发现A没有变化,就误以为是原来的那个A。这就是有名的ABA问题。ABA问题会带来什么后果呢?我们举个例子。

一个小偷,把别人家的钱偷了之后又还了回来,还是原来的钱吗,你老婆出轨之后又回来,还是原来的老婆嘛?ABA问题也一样,如果不好好解决就会带来大量的问题。最常见的就是资金问题,也就是别人如果挪用了你的钱,在你发现之前又还了回来。但是别人却已经触犯了法律。

如何去解决这个ABA问题呢,就是使用下面的AtomicStampedReference
使用一个版本号去维护,如果发现版本不一致就不更新

class Test {
    
    
    static AtomicInteger balance = new AtomicInteger(100);

    static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 0);

    public static void main(String[] args) throws InterruptedException {
    
    
        System.out.println("ABA问题:当前值" + balance.get());
        //模拟主线程改动变量时,其他线程更改了变量
        new Thread(() -> System.out.println("thread1:100改成90," + balance.compareAndSet(100, 90))).start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(() -> System.out.println("thread2:90改成100," + balance.compareAndSet(90, 100))).start();
        TimeUnit.SECONDS.sleep(1);
        //上面的线程改成别的值,然后又改回来,但是主线程没发现,以为是原来的,所以更改成功了
        System.out.println("main1:100改成90," + balance.compareAndSet(100, 90));

        System.out.println("\nABA问题解决:当前值" + atomicStampedReference.getReference());
        int mstamp = atomicStampedReference.getStamp();
        System.out.println("main2:当前版本:" + mstamp);
        //模拟主线程改动变量时,其他线程更改了变量
        new Thread(() -> {
    
    
            int stamp = atomicStampedReference.getStamp();
            System.out.println("thread3:100改成90,当前版本=" + atomicStampedReference.getStamp() + "," + atomicStampedReference.compareAndSet(100, 90, stamp, stamp + 1));

        }).start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(() -> {
    
    
            int stamp = atomicStampedReference.getStamp();
            System.out.println("thread4:90改成100,当前版本=" + atomicStampedReference.getStamp() + "," + atomicStampedReference.compareAndSet(90, 100, stamp, stamp + 1));
        }).start();
        TimeUnit.SECONDS.sleep(1);
        //期间mstamp被更改过,所以这里更新失败
        System.out.println("main2:100改成90,当前版本=" + atomicStampedReference.getStamp() + "," + atomicStampedReference.compareAndSet(100, 90, mstamp, mstamp + 1));
    }
    
}

结果

ABA问题:当前值100
thread1:100改成90true
thread2:90改成100true
main1:100改成90,true

ABA问题解决:当前值100
main2:当前版本:0
thread3:100改成90,当前版本=0,true
thread4:90改成100,当前版本=1,true
main2:100改成90,当前版本=2,false

猜你喜欢

转载自blog.csdn.net/Fire_Sky_Ho/article/details/128323575
今日推荐