什么是ABA问题

在CAS算法中,需要取出内存中某时刻的数据(由用户完成),在下一时刻比较并交换(CPU保证原子操作),这个时间差会导致数据的变化。

1、线程1从内存位置V中取出A
2、线程2从内存位置V中取出A
3、线程2进行了写操作,将B写入内存位置V
4、线程2将A再次写入内存位置V
5、线程1进行CAS操作,发现V中仍然是A,交换成功

尽管线程1的CAS操作成功,但线程1并不知道内存位置V的数据发生过改变

ABA问题本质:

根本在于CAS在修改变量的时候,无法记录变量的状态,比如是否修改过这个变量,修改的次数。

public class ABADemo {

    private static AtomicReference<Integer> atomicReference = new AtomicReference<Integer>();

    public static void main(String[] args) {
new Thread(() -> {
Integer a = atomicReference.get();
atomicReference.compareAndSet(a, );
atomicReference.compareAndSet(, a);
System.out.println("t1修改了atomicReference的值");
},"t1").start(); new Thread(() -> {
Integer b = atomicReference.get();
try {
Thread.sleep();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(atomicReference.compareAndSet(b, ) + "\t修改后的值:" + atomicReference.get());
},"t2").start();
}
}

ABA问题怎么解决

public class AtomicStampedReferenceTest {

    private static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<Integer>(,);

    public static void main(String[] args) {
new Thread(() -> {
Integer stamp = atomicStampedReference.getStamp();
System.out.println("t1拿到的初始版本号:" + stamp);
//睡眠1秒,是为了让t2线程也拿到同样的初始版本号
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
atomicStampedReference.compareAndSet(, ,stamp,stamp+);
stamp = atomicStampedReference.getStamp();
atomicStampedReference.compareAndSet(, ,stamp,stamp+);
},"t1").start(); new Thread(() -> {
int stamp = atomicStampedReference.getStamp();
System.out.println("t2拿到的初始版本号:" + stamp);
//睡眠3秒,是为了让t1线程完成ABA操作
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("最新版本号:" + atomicStampedReference.getStamp());
System.out.println(atomicStampedReference.compareAndSet(, ,stamp,atomicStampedReference.getStamp() + ) + "\t当前 值:" + atomicStampedReference.getReference());
},"t2").start();
}
}

如果不关心引用变量更改了几次,只单纯的关心是否更改过,可以使用AtomicMarkableReference

public class ABADemo {

    private static AtomicMarkableReference<Integer> atomicMarkableReference = new AtomicMarkableReference<Integer>(,false);

    public static void main(String[] args) {
new Thread(() -> {
System.out.println("t1版本号是否被更改:" + atomicMarkableReference.isMarked());
//睡眠1秒,是为了让t2线程也拿到同样的初始版本号
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
atomicMarkableReference.compareAndSet(, ,false,true); },"t1").start(); new Thread(() -> {
boolean isMarked = atomicMarkableReference.isMarked();
System.out.println("t2版本号是否被更改:" + isMarked);
//睡眠3秒,是为了让t1线程执行
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("是否更改过:" + atomicMarkableReference.isMarked());
System.out.println(atomicMarkableReference.compareAndSet(, ,isMarked,true) + "\t当前 值:" + atomicMarkableReference.getReference());
},"t2").start();
}
}

ABA问题的产生及解决的更多相关文章

  1. CAS与ABA问题产生和优雅解决

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  2. CAS如何解决ABA问题

    点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. CAS如何解决ABA问题 什么是ABA:在CAS过程中,线程1.线程2分 ...

  3. ABA问题怎么解:AtomicStampedReference和AtomicMarkableReference

    本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 并发编程的基石--CAS机制这篇文章中介绍到CAS机制有 ...

  4. CAS 和 ABA 问题

    CAS简介 CAS 全称是 compare and swap,是一种用于在多线程环境下实现同步功能的机制. CAS 它是一条CPU并发原语.操作包含三个操作数 -- 内存位置.预期数值和新值.CAS ...

  5. 原子类的ABA问题

    原子类AtomicInteger的ABA问题 连环套路 从AtomicInteger引出下面的问题 CAS -> Unsafe -> CAS底层思想 -> ABA -> 原子引 ...

  6. CAS底层原理与ABA问题

    CAS定义 CAS(Compare And Swap)是一种无锁算法.CAS算法是乐观锁的一种实现.CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B.当预期值A和内存值V相同时,将内存值V修 ...

  7. Java多线程_CAS算法和ABA问题

    CAS算法概述CAS是英文单词CompareAndSwap的缩写,中文意思是:比较并替换.CAS需要有3个操作数:内存地址V,旧的预期值A,即将要更新的目标值B. CAS指令执行时,当且仅当内存地址V ...

  8. JUC学习笔记--Atomic原子类

    J.U.C 框架学习顺序 http://blog.csdn.net/chen7253886/article/details/52769111 Atomic 原子操作类包 Atomic包 主要是在多线程 ...

  9. 【Bugly干货】Android性能优化典范之多线程篇

    本文涉及的内容有:多线程并发的性能问题,介绍了 AsyncTask,HandlerThread,IntentService 与 ThreadPool 分别适合的使用场景以及各自的使用注意事项,这是一篇 ...

随机推荐

  1. 如何down掉IB交换机口

    服务器上找到需down的网络:ip a 通过ib命令iblinkinfo找到对应交换机以及在ib交换机上对应端口号 登录IB交换机,并通过命令:config进入配置模式 通过命令:port进入端口配置 ...

  2. SpringBoot打可执行war包

    1. 主程序类: @SpringBootApplication public class Application extends SpringBootServletInitializer { @Ove ...

  3. webpack4 plugins 篇

    demo 代码点此,篇幅有限,仅介绍几个常用的. start 什么是 plugins ? While loaders are used to transform certain types of mo ...

  4. php动态拼接变量名,可变变量,动态变量,使用花括号,使用两个$符

    php动态拼接变量名,可变变量,动态变量,使用花括号,使用两个$符方式一:使用花括号,前缀部分不需要用单引号$nums10 = 100;$xxx*${bcount.$nums10}['m54']/$n ...

  5. 如何在unbuntu 16.04上离线部署openssh

    背景:由于部署环境不能联网,为了方便文件传输,需要用到openssh.故实施步骤是,先在可以联网机器上下载离线包,然后用U盘拷贝到部署环境中. 第一步:下载离线包,下载网址:https://packa ...

  6. jar 冲突、class 冲突的检测脚本

    思路很简单,解开war包,解开 jar 包,发现有同名 package.class 就报出来,不管是否“兼容” .. import zipfile import io from collections ...

  7. poi操作Word创建超链接

    项目引入poi: <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</ ...

  8. 3-3 groupby操作

    Pandas章节应用的数据可以在以下链接下载:  https://files.cnblogs.com/files/AI-robort/Titanic_Data-master.zip .caret, . ...

  9. 如何下载Youtube的4K视频?这里有4款软件, 哪个适合你?

    数字电影的最新分辨率标准是4k,4K分辨率的视频具有高图像清晰度质量.更好的快速动作.更大的投影表面可见度和更详细的图像质量等优点,受到了广大视频爱好者的好评.作为当前最火热的视频分享网站,YouTu ...

  10. jmeter压测学习8-压测带token的接口

    前言 工作中我们需要压测的接口大部分都是需要先登陆后,带着token的接口(或者带着cookies),我们可以先登陆获取token再关联到下个接口. 比如我现在要压测一个修改用户的个人信息接口,每个用 ...