【构建并发程序】4-原子变量-CAS-ABA问题

原子变量中CAS的ABA问题


原子变量的这种CAS看起来很爽,但是有可能会导致ABA问题。

什么是ABA问题?

简单点就是,3个线程对某个原子变量val inte = new AutoicInteger(1)进行操作

  • A线程要做inte.compareAndSet(1,2)
  • B线程要做inte.compareAndSet(1,3)
  • C线程要做inte.compareAndSet(3,1)
  1. A线程没抢过B,C两个线程,且BC两个线程中,B线程先执行的,然后是C线程,当C线程执行完后inte的内存地址已发生过两次偏移,新的地址值是1。
  2. A线程要做的是将inte的值变成2,当它从地址中进行读取的时候发现值是1正确,所以会赋值一个2,但是这里的inte地址已经不是当初新创建的那个地址了(因为内存地址发生过两次偏移);

ABA问题会导致的后果

 ABA问题在只需要比对数值的这种情况下是没有问题的,例如查询库存量,然后进行相应的删除或修改。
但在堆栈操作中就会出现问题了如下(假设有如下场景):

  1. 一个用单向链表实现的栈结构,栈顶元素为A。
  2. 这时线程1已经知道A.next为B,然后希望用CAS将栈顶替换为B;
    在这里插入图片描述
  3. 在线程1执行上面这条指令之前,线程2先得到执行,并且线程2将A、B两个元素依次出栈,再将D、C、A元素压入栈中。对象B此时处于游离状态,栈结构如下:
    在这里插入图片描述
  4. 此时轮到线程1进行CAS操作,检测发现栈顶仍然是A,所以CAS成功,栈顶元素变为B,但实际上B.next为null,所以此时的情况变为:栈中只有B一个元素,C和D不再存在于栈中,这样C和D元素就丢了。

(本文章虽然采用的代码为scala代码,但java代码与Scala代码可以互相转换,且本质上两者所阐述的东西都是一致的)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值