文章目录

  • ABA问题
      • 发生ABA问题示例代码
    • 带版本号的原子操作
      • 解决ABA问题实例代码:
    • LongAdder

ABA问题

CAS 需要检查操作值有没有发生改变,如果没有发生改变则更新。但是存在这样一种情况:如果一个值原来是A,变成了B,然后又变成了A,那么在CAS检查的时候会发现没有改变,但是实质上它已经发生了改变,这就是所谓的ABA问题。

狸猫换太子:将原来的数换为另一个数,操作完成后再换回去,且不被人发现


CAS算法实现了一个重要的前提,需要取出内存中某时刻的数据,并在当下时刻比较并替换,那么这个时间差会导致数据的变化。
对于ABA问题其解决方案是加上版本号,即在每个变量都加上一个版本号,每次改变时加1,即A —> B —> A,变成A1 —> B2 —> A3。

JUC包中提供了一个AtomicStampedReference类来解决ABA问题。 AtomicStampedReference 本质是有一个int 值作为版本号,每次更改前先取到这个int值的版本号,等到修改的时候,比较当前版本号与当前线程持有的版本号是否一致,如果一致,则进行修改,并将版本号加1,在zookeeper中保持数据的一致性也是用的这种方式;

此外,JUC包中还有一个AtomicMarkableReference类,这个类则是将一个boolean值作是否有更改的标记,本质就是它的版本号只有两个,true和false,修改的时候在这两个版本号之间来回切换,这样做并不能解决ABA的问题。

发生ABA问题示例代码

public class CASDemo {public static void main(String[] args) {AtomicInteger atomicInteger = new AtomicInteger(2020);//CAS--比较并交换//如果期望值找到了就更新,负责不更新//CAS 是CPU的并发原语//===========捣乱线程=========================System.out.println(atomicInteger.compareAndSet(2021, 2022));System.out.println(atomicInteger.get());System.out.println(atomicInteger.compareAndSet(2022, 2021));System.out.println(atomicInteger.get());//==========期望线程System.out.println(atomicInteger.compareAndSet(2021, 6666));System.out.println(atomicInteger.get());}
}

结果:

true
2022
true
2021
true
6666

将2021转换为2022后在转换回原值,期望线程并未发现异常,普通的原子类并不能解决

带版本号的原子操作


解决ABA问题实例代码:

所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较

说明:对于 Integer var = ? 在-128 至 127 范围内的赋值,Integer 对象是在 IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。

public class CASDemo {static AtomicStampedReference<Integer> atomicInteger = new AtomicStampedReference<>(1, 1);public static void main(String[] args) {//ABA线程new Thread(() -> {//返回当前值int stamp = atomicInteger.getReference();System.out.println("a1-->"+stamp);try{TimeUnit.SECONDS.sleep(2);}catch (InterruptedException e){e.printStackTrace();}//将1转换为2System.out.println(atomicInteger.compareAndSet(1, 2, atomicInteger.getStamp(), atomicInteger.getStamp() + 1));System.out.println("a2-->"+stamp);//将2转换为1System.out.println(atomicInteger.compareAndSet(2, 1, atomicInteger.getStamp(), atomicInteger.getStamp() + 1));System.out.println("a3-->"+stamp);}, "a").start();//普通线程new Thread(() -> {int stamp = atomicInteger.getReference();System.out.println("b-->"+stamp);try{TimeUnit.SECONDS.sleep(2);}catch (InterruptedException e){e.printStackTrace();}System.out.println(atomicInteger.compareAndSet(1, 6, atomicInteger.getStamp(), atomicInteger.getStamp() + 1));System.out.println("b2-->"+stamp);}, "b").start();}
}

结果:

a1-->1
b-->1
true
b2-->1
false
a2-->1
false
a3-->1

从结果可以看出有效防止了ABA问题

LongAdder

LongAdder

ABA-->狸猫换太子之法相关推荐

  1. JVM、JUC、网络、线程

    1. JVM 面试常见: 请你谈谈你对 JVM 的理解? java 8 虚拟机和之前的变化更新? 什么是 OOM,什么是栈溢出 StackOverFlowError? 怎么分析? JVM的常用调优参数 ...

  2. 单链表删除元素之狸猫换太子法

    狸猫换太子法 删除链表元素 条件:单链表 仅仅给一个结点*(未给head指针) * 要求:删除该结点 算法思路:(假删除)通过将下一个结点的值赋给当前结点,再删除下一个节点,达到删除效果 (找下一个结 ...

  3. ABA问题(狸猫换太子)

    解决ABA问题:引入原子引用! 并发1在修改数据时,虽然还是A,但已经不是初始条件的A了,中间发生了A变B,B又变A的变化,此A已经非彼A,数据却成功修改,可能导致错误,这就是CAS引发的所谓的ABA ...

  4. 聊聊电商系统中常见的9大坑,库存超卖、重复下单、物流单ABA...

    做为一名程序员,发展方向大致可以分为两个方面:一个是业务架构,一个是技术架构(中间件方向). 业务架构,取其核心关键词,主要是围绕这不同的业务场景.业务规则,完成业务系统的落地建设,为用户提供在线化的 ...

  5. leetcode 5. 最长回文子串 暴力法、中心扩展算法、动态规划,马拉车算法(Manacher Algorithm)

    给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000.示例 1: 输入: "babad" 输出: "bab" 注意: &quo ...

  6. [剑指offer]面试题第[38]题[JAVA][字符串的排列][回溯法]

    [问题描述][中等] 输入一个字符串,打印出该字符串中字符的所有排列. 你可以以任意顺序返回这个字符串数组,但里面不能有重复元素.示例: 输入:s = "abc" 输出:[&quo ...

  7. CAS 乐观锁和ABA问题

    CAS====>Compare-And-Swap 如果主物理内存的值跟线程期望值一样,就修改为我的更新值,不一样,就失败,需要重新获取主物理内存的值 底层基于usafe,而这个类是rt.jar包 ...

  8. aba会导致问题_ABA问题

    什么是ABA问题? 简单来说就是:狸猫换太子. 假设这里有两个线程线程1和线程2,线程1工作时间需要10秒,线程2工作需要2秒,主内存值为A,第一轮线程1和线程2都把A拿到自己的工作内存,2秒中后线程 ...

  9. 线代中最基础的两种玩法

    线代中最基础的两种玩法 @(线性代数) 加法 乘法 由这两种最基础的做法可以发展出许多有意思的解题思路. 以可交换矩阵的论证为例. 可交换矩阵:AB=BA 一般有三类: 单位矩阵,或零矩阵 AE = ...

最新文章

  1. java B2B2C springmvc mybatis多租户电子商城系统(五):熔断监控Hystrix Dashboard和Turbine...
  2. javascript之DOM操作
  3. 记录 centos samba 安装
  4. Socket网络编程--小小网盘程序(1)
  5. JUC包中的分而治之策略-为提高性能而生 1
  6. python快速入门及进阶
  7. macOS Mojave下解决wine中文乱码问题
  8. 三、Serializer序列化器
  9. 免费站群系统cm-SEO需要多长时间?
  10. 【SpringBoot实现企业微信会话内容存档】linux部署
  11. Java温习——SUN公司和Java平台
  12. Reflector、ReflectorFactory的前世
  13. Neo4j 爬坑笔记for3.2.6
  14. 函数右括号错误! PreTranslateMessage(MSG* pMsg)未返回
  15. 逆向某停车app(原创)
  16. Android-Application被回收引发空指针异常分析(消灭全局变量)
  17. 【ABviewer从零开始教学查看器篇①】3D查看器和3D剖面板
  18. 如何招到一个靠谱的程序员,以及如何应对面试题
  19. nginx配置区分移动端和PC端,访问不同域名
  20. 多个PDF合并到一个PDF

热门文章

  1. nginx下使用SSI
  2. 在月亮湖捡到鸿蒙,在腾格里沙漠深处,有6000万年前的湖泊,水深4米
  3. python中cd是什么意思_改变当前路径 (cd)
  4. vue移动端下拉刷新、上拉加载
  5. 在南方读研和在北方读研有多大差异?
  6. 如何将文字翻译成英文?简单教程讲解
  7. 希腊罗马神话传说和《圣经》中的英语成语典故
  8. 0-1型整数规划—MATLAB数学建模
  9. iptables白名单
  10. 从华为清理34岁以上老员工想起的二三事