JAVA中CAS-ABA的问题解决方案AtomicStampedReference

​什么是CAS?
CAS即对比交换,它在保证数据原子性的前提下尽可能的减少了锁的使用

ABA问题

线程1准备用CAS修改变量值A,在此之前,其它线程将变量的值由A替换为B,又由B替换为A,然后线程1执行CAS时发现变量的值仍然为A,所以CAS成功。但实际上这时的现场已经和最初不同了。
在这里插入图片描述
例子

 private static void atomicIntegerABA() {
        Thread main = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("操作线程" + Thread.currentThread() + ",初始值 = " + atomicInteger);  //定义变量 a = 1
                try {
                    Thread.sleep(1000); //等待1秒 ,以便让干扰线程执行
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                boolean isCASSuccess = atomicInteger.compareAndSet(1, 2); //CAS操作
                System.out.println("操作线程" + Thread.currentThread() + ",CAS操作结果: " + isCASSuccess);
            }
        }, "主操作线程");

        Thread other = new Thread(new Runnable() {
            @Override
            public void run() {
                Thread.yield();  //确保thread-main线程优先执行
                atomicInteger.incrementAndGet(); // a 加 1, a + 1 = 1 + 1 = 2
                System.out.println("操作线程" + Thread.currentThread() + ",【increment】 ,值 = " + atomicInteger);
                atomicInteger.decrementAndGet(); // a 减 1, a - 1 = 2 - 1 = 1
                System.out.println("操作线程" + Thread.currentThread() + ",【decrement】 ,值 = " + atomicInteger);
            }
        }, "干扰线程");

        main.start();
        other.start();
    }

输出结果

操作线程Thread[主操作线程,5,main],初始值 = 1
操作线程Thread[干扰线程,5,main],【increment】 ,= 2
操作线程Thread[干扰线程,5,main],【decrement】 ,= 1
操作线程Thread[主操作线程,5,main],CAS操作结果: true

解决ABA方案

思路
解决ABA最简单的方案就是给值加一个修改版本号,每次值变化,都会修改它版本号,CAS操作时都对比此版本号。
在这里插入图片描述
JAVA中ABA中解决方案(AtomicStampedReference)
AtomicStampedReference主要维护包含一个对象引用以及一个可以自动更新的整数"stamp"的pair对象来解决ABA问题。

private static void atomicStampedRefABA() {
        int stamp = atomicStampedRef.getStamp(); //获取当前标识别
        Thread main = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("操作线程" + Thread.currentThread() + ",初始值 = " + atomicStampedRef.getReference());  //定义变量 a = 1
                try {
                    Thread.sleep(1000); //等待1秒 ,以便让干扰线程执行
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                boolean isCASSuccess = atomicStampedRef.compareAndSet(1, 2, stamp, stamp + 1); //CAS操作
                System.out.println("操作线程" + Thread.currentThread() + ",CAS操作结果: " + isCASSuccess);
            }
        }, "主操作线程");

        Thread other = new Thread(new Runnable() {
            @Override
            public void run() {
                Thread.yield();  //确保thread-main线程优先执行
                atomicStampedRef.compareAndSet(1, 2, stamp, stamp + 1);
                System.out.println("操作线程" + Thread.currentThread() + ",【increment】 ,值 = " + atomicStampedRef.getReference());
                atomicStampedRef.compareAndSet(2, 1, stamp, stamp + 1);
                System.out.println("操作线程" + Thread.currentThread() + ",【decrement】 ,值 = " + atomicStampedRef.getReference());
            }
        }, "干扰线程");
        main.start();
        other.start();
    }

输出结果

操作线程Thread[主操作线程,5,main],初始值 = 1
操作线程Thread[干扰线程,5,main],【increment】 ,= 2
操作线程Thread[干扰线程,5,main],【decrement】 ,= 2
操作线程Thread[主操作线程,5,main],CAS操作结果: false
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值