ABA问题及解决

ABA问hiyi题:
在多线程环境下,一个线程需要修改共享变量的值,使用CAS操作时,当其他线程将该共享变量由A该为B,再将B改为A后,这个线程依然可以CAS操作成功,因为这个线程不能感知这个共享变量被修改过

解决方法:给共享变量增加一个版本号,在CAS操作时不仅比较值是否相等,还比较版本号是否相等,,,因为所有的线程使用共享变量时都遵循相同的规则:给版本号加1

代码示例:
@Slf4j(topic = "c.TestABA")
public class TestABA {
    static AtomicStampedReference<String> ref=new AtomicStampedReference<>("A",0);
    public static void main(String[] args) throws InterruptedException {

        log.debug("main  start....");
        //获取值 A,获取版本号0
        //这个共享变量被其他线程修改过?
        String prev=ref.getReference();
        int stamp=ref.getStamp();
       log.debug("{}",stamp);
        other();
        TimeUnit.SECONDS.sleep(3);
        //尝试改为C
        log.debug("change A->C {}",ref.compareAndSet(prev,"C",stamp,stamp+1));

    }
    private static void other() throws InterruptedException {
        new Thread(()->{
            int stamp=ref.getStamp();
            log.debug("changeA->B{}",ref.compareAndSet(ref.getReference(),"B",stamp,stamp+1));
            log.debug("{}",stamp);
        },"t1").start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            int stamp=ref.getStamp();
            log.debug("changeB->A{}",ref.compareAndSet(ref.getReference(),"A",stamp,stamp+1));
            log.debug("{}",stamp);
        },"t2").start();
    }
}

运行结果:
08:50:26.076 [main] DEBUG c.TestABA - main start…
08:50:26.078 [main] DEBUG c.TestABA - 0
08:50:26.119 [t1] DEBUG c.TestABA - changeA->Btrue
08:50:26.119 [t1] DEBUG c.TestABA - 0
08:50:27.125 [t2] DEBUG c.TestABA - changeB->Atrue
08:50:27.125 [t2] DEBUG c.TestABA - 1
08:50:30.128 [main] DEBUG c.TestABA - change A->C false

结果分析:
一开始主线程先启动,去获取共享变量的值和版本号后,去调用other方法这个方法中启动两个线程去修改A与B的值,修改的规则一致:获取当前值和版本号,用CAS比较并设置,这个other()执行完成后,主线程再进行CAS操作时发现版本号被修改,此次的CAS将失败: change A->C false

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值