1.CAS导致ABA问题:

CAS算法实现一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并交换,那么在这个时间差中会导致数据的变化。

比如:线程1从内存位置V中取出A,这时线程2也从V中取出A,线程2进行了一些操作将值改成了B,然后线程2又将V的数据改回A;此时线程1进行CAS操作发现内存中仍然是A,然后线程1操作成功。

尽管线程1的CAS操作成功,但是不代表这个过程就是没有问题的

解决ABA问题:利用原子引用+修改版本号(类似时间戳),每次需要获取到版本最新的值进行处理。

2.原子引用AtomicReference

ABA问题出现示例:

package com.mort.test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference; public class TestAtomicReference { static AtomicReference<Integer> atomicReference = new AtomicReference<Integer>(100);
public static void main(String[] args) {
new Thread(() -> {
// 执行ABA操作
atomicReference.compareAndSet(100, 101);
atomicReference.compareAndSet(101, 100);
}, "t1").start(); new Thread(()->{
// 暂停1秒钟t2线程,保证t1完成了一次ABA操作
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicReference.compareAndSet(100, 2019)+"\t" + atomicReference.get());
}, "t2").start();
}
}

3.解决ABA问题:时间戳原子引用AtomicStampedReference

代码示例:

package com.mort.test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference; public class TestABASolve {
//static AtomicReference<Integer> atomicReference = new AtomicReference<Integer>(100);
static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100,1);
public static void main(String[] args) {
new Thread(() -> {
int stamp = atomicStampedReference.getStamp();
System.out.println(Thread.currentThread().getName()+"\t第1次版本号:"+stamp);
// 暂停1秒钟t1线程,保证t2拿到版本号与t1相同
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 执行ABA操作
atomicStampedReference.compareAndSet(100, 101,stamp,stamp+1);
stamp = atomicStampedReference.getStamp();
System.out.println(Thread.currentThread().getName()+"\t第2次版本号:"+stamp);
atomicStampedReference.compareAndSet(101, 100, stamp,stamp+1);
// System.out.println(Thread.currentThread().getName()+"\t第3次版本号:"+atomicStampedReference.getStamp());
}, "t1").start(); new Thread(()->{
int stamp = atomicStampedReference.getStamp();
System.out.println(Thread.currentThread().getName()+"\t第1次版本号:"+stamp);
// 暂停3秒钟t2线程,保证t1完成了一次ABA操作
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean result = atomicStampedReference.compareAndSet(100, 2019, stamp, stamp+1);
System.out.println(Thread.currentThread().getName()+"\t执行结果:"+result+"\t最新版本号:"+atomicStampedReference.getStamp());
System.out.println(Thread.currentThread().getName()+"\t当前实际最新值:"+atomicStampedReference.getReference());
}, "t2").start();
}
}

输出结果:

t1    第1次版本号:1
t2 第1次版本号:1
t1 第2次版本号:2
t2 执行结果:false 最新版本号:3
t2 当前实际最新值:100

CAS导致的ABA问题及解决:时间戳原子引用AtomicReference、AtomicStampedReference的更多相关文章

  1. CAS导致的ABA问题以及解决方案

    CAS算法实现一个重要前提需要取出内存中某时刻的数据,而在下时刻比较并替换,那么在这个时间差类会导致数据的变化. 上篇文章讲到CAS会出现一个ABA问题.那什么是ABA问题呢? 官方一点的解释就是:当 ...

  2. 一篇文章快速搞懂 Atomic(原子整数/CAS/ABA/原子引用/原子数组/LongAdder)

    前言 相信大部分开发人员,或多或少都看过或写过并发编程的代码.并发关键字除了Synchronized,还有另一大分支Atomic.如果大家没听过没用过先看基础篇,如果听过用过,请滑至底部看进阶篇,深入 ...

  3. JUC 并发编程--05, Volatile关键字特性: 可见性, 不保证原子性,禁止指令重排, 代码证明过程. CAS了解么 , ABA怎么解决, 手写自旋锁和死锁

    问: 了解volatile关键字么? 答: 他是java 的关键字, 保证可见性, 不保证原子性, 禁止指令重排 问: 你说的这三个特性, 能写代码证明么? 答: .... 问: 听说过 CAS么 他 ...

  4. AtomicStampedReference AtomicReference解决CAS机制中ABA问题

    AtomicStampedReference AtomicReference解决CAS机制中ABA问题 AtomicStampedReference AtomicStampedReference它内部 ...

  5. 基于CAS分析对ABA问题的一点思考

    基于CAS分析对ABA问题的一点思考 什么是CAS? 背景 synchronized加锁消耗太大 volatile只保证可见性,不保证原子性 基础 用CPU提供的特殊指令,可以: 自动更新共享数据; ...

  6. 记一次由于Java泛型类型擦除而导致的问题,及解决办法

    中所周知,Java中的泛型并不像C++.C#一样是真正的泛型,其泛型是通过类型擦除来实现的.具体什么是类型擦除,可以参看这篇博文:http://icyfenix.iteye.com/blog/1021 ...

  7. 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(中)- IOS不为人知的Bug

    前言: 话说昨晚还是前晚,写了一篇:讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(上) 文章写到最后时,多了很多莫名奇妙的问题!!! 为了解决了这些莫名奇妙的问题,我又战斗了2 ...

  8. 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(下)- block中任性用self

    前言: 在处理完框架内存泄漏的问题后,见上篇:讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(中)- IOS不为人知的Bug 发现业务代码有一个地方的内存没释放,原因很也简单: ...

  9. 关于FusionCharts图表宽度width的设置问题导致图表显示异常的解决办法

    关于FusionCharts图表宽度width的设置问题导致图表显示异常的解决办法 题设: 经常使用FusionCharts图表的朋友可能会遇到这个问题.就是在FusionCharts显示的时候有时候 ...

随机推荐

  1. k8s-wordpress

    将数据库的密码写入wordpress的yaml配置文件不行,额外输入可以初始化数据成功,好奇怪 mysql 配置yamL cat mysql.yml --- apiVersion: apps/v1be ...

  2. StreamWriter、StreamReader

    IO流操作文件内容,using System.IO;//引入命名空间 private void button1_Click(object sender, EventArgs e) { if (text ...

  3. BZOJ 2434: [Noi2011]阿狸的打字机 AC自动机+fail树+线段树

    Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...

  4. Nowcoder Sum of Maximum ( 容斥原理 && 拉格朗日插值法 )

    题目链接 题意 : 分析 : 分析就直接参考这个链接吧 ==> Click here 大体的思路就是 求和顺序不影响结果.故转化一下思路枚举每个最大值对答案的贡献最后累加就是结果 期间计数的过程 ...

  5. 文件操作:fseek()

    int fseek(FILE *stream, long offset, int fromwhere); fseek 用于二进制方式打开的文件,移动文件读写指针位置.   int fseek( FIL ...

  6. 51 nod 1127最短的包含字符串(尺取法)

    1127 最短的包含字符串   收藏  关注 给出一个字符串,求该字符串的一个子串S,S包含A-Z中的全部字母,并且S是所有符合条件的子串中最短的,输出S的长度.如果给出的字符串中并不包括A-Z中的全 ...

  7. react-router-dom 实现左侧导航

    1.介绍react-router-dom https://reacttraining.com/react-router/web/example/basic 这个官网有很多栗子可以练手 1.1 Hash ...

  8. R_Studio(聚类)针对iris数据比较几种聚类方法优劣

    聚类分析 百度百科:传送门 聚类分析指将物理或抽象对象的集合分组为由类似的对象组成的多个类的分析过程 聚类与分类的不同在于,聚类所要求划分的类是未知的 聚类分析是一种探索性的分析,在分类的过程中,人们 ...

  9. Hibernate动态条件查询(Criteria Query)

    1.创建一个Criteria实例net.sf.hibernate.Criteria这个接口代表对一个特定的持久化类的查询.Session是用来制造Criteria实例的工厂. Criteria cri ...

  10. CppCheck介绍与使用

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u011012932/article/details/52778149 简述 Cppcheck 是一种 ...