CAS中的ABA问题

一、什么是CAS?

  CAS(compare and set)操作是多线程环境处理并发的原子操作,更新一个值前先比较,如果与预期值一样则更新,否则失败。CAS底层是通过汇编层面的原语调用cpu指令实现的,同时结合了内存屏障,具体依赖CPU的指令,如cmpxchg指令(X86架构)

二、什么是ABA问题?

  现有线程t1和线程t2,共享变量str="A"

    ① 首先读取str,那么t1中缓存值为A,t2中缓存值也为A,

    ② 紧接着t2修改str为B(str="B"),然后又修改str为A(现在str="A")

  由于t1中缓存值为A,内存中str也为"A",t1线程就会误以为str没有被修改过。

 ABA问题最核心在于t1错误的认为str没有被修改过

 补充:线程对共享变量的缓存在处理当前线程的CPU中(L1、L2、L3缓存,速度远比内存快)

三、ABA问题的影响

  小明有10000元,取5000,有两个线程处理

    ① 线程t1、t2读取小明的10000元

    ② 线程t1由于某种原因阻塞,线程t2比较发现预期值(10000块)与实际值(10000块)相等,那么扣减5000块,现在小明还剩5000块

    ③ 按道理说t2执行完,t1的预期值(10000)与实际值(5000)不相等,应该结束才对。

    ④ 但是此时有人给小明转账5000元,那么小明的钱又变成了10000,

    ⑤ 突然线程t1恢复了,开始执行CAS操作,发现实际值与预期值一样,然后便将10000修改为5000

  结果:小明白白损失5000块!!

四、如何解决ABA问题?

    可以给数据加上时间戳或版本号,记录修改时间或版本号+1,让每次操作都留下痕迹。

    在java中可以使用AtomicStampedReference类,它结合了值和版本号,每次修改时都会比较值和版本号是否相同,如果相同,则同时修改值和版本号

你可能感兴趣的:(CAS中的ABA问题)