CAS导致的ABA问题及解决:时间戳原子引用AtomicReference、AtomicStampedReference
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的更多相关文章
- CAS导致的ABA问题以及解决方案
CAS算法实现一个重要前提需要取出内存中某时刻的数据,而在下时刻比较并替换,那么在这个时间差类会导致数据的变化. 上篇文章讲到CAS会出现一个ABA问题.那什么是ABA问题呢? 官方一点的解释就是:当 ...
- 一篇文章快速搞懂 Atomic(原子整数/CAS/ABA/原子引用/原子数组/LongAdder)
前言 相信大部分开发人员,或多或少都看过或写过并发编程的代码.并发关键字除了Synchronized,还有另一大分支Atomic.如果大家没听过没用过先看基础篇,如果听过用过,请滑至底部看进阶篇,深入 ...
- JUC 并发编程--05, Volatile关键字特性: 可见性, 不保证原子性,禁止指令重排, 代码证明过程. CAS了解么 , ABA怎么解决, 手写自旋锁和死锁
问: 了解volatile关键字么? 答: 他是java 的关键字, 保证可见性, 不保证原子性, 禁止指令重排 问: 你说的这三个特性, 能写代码证明么? 答: .... 问: 听说过 CAS么 他 ...
- AtomicStampedReference AtomicReference解决CAS机制中ABA问题
AtomicStampedReference AtomicReference解决CAS机制中ABA问题 AtomicStampedReference AtomicStampedReference它内部 ...
- 基于CAS分析对ABA问题的一点思考
基于CAS分析对ABA问题的一点思考 什么是CAS? 背景 synchronized加锁消耗太大 volatile只保证可见性,不保证原子性 基础 用CPU提供的特殊指令,可以: 自动更新共享数据; ...
- 记一次由于Java泛型类型擦除而导致的问题,及解决办法
中所周知,Java中的泛型并不像C++.C#一样是真正的泛型,其泛型是通过类型擦除来实现的.具体什么是类型擦除,可以参看这篇博文:http://icyfenix.iteye.com/blog/1021 ...
- 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(中)- IOS不为人知的Bug
前言: 话说昨晚还是前晚,写了一篇:讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(上) 文章写到最后时,多了很多莫名奇妙的问题!!! 为了解决了这些莫名奇妙的问题,我又战斗了2 ...
- 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(下)- block中任性用self
前言: 在处理完框架内存泄漏的问题后,见上篇:讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(中)- IOS不为人知的Bug 发现业务代码有一个地方的内存没释放,原因很也简单: ...
- 关于FusionCharts图表宽度width的设置问题导致图表显示异常的解决办法
关于FusionCharts图表宽度width的设置问题导致图表显示异常的解决办法 题设: 经常使用FusionCharts图表的朋友可能会遇到这个问题.就是在FusionCharts显示的时候有时候 ...
随机推荐
- Documents.Open返回值为null
上个月出现的一个问题,将解决方法记录一下~ [问题]无法通过SAP系统外部OS命令(SM69)执行OS服务器上Powershell文件对Office文档的相关命令操作(打开文档等命令). [现象]执行 ...
- touch:创建文件及修改文件时间戳
touch 命令不光可以用来创建文件(当指定操作文件不存在时,该命令会在当前位置建立一个空文件),此命令更重要的功能是修改文件的时间参数(但当文件存在时,会修改此文件的时间参数). Linux 系统中 ...
- react-router-dom 实现左侧导航
1.介绍react-router-dom https://reacttraining.com/react-router/web/example/basic 这个官网有很多栗子可以练手 1.1 Hash ...
- apply,call,bind函数作用与用法
作用 可以把方法借给其它对象使用,并且改变this的指向 a.apply(b,[3,2]);//this指向由a变为b, a的方法借给b使用 实例: function add(a,b){ ...
- R_针对churn数据用id3、cart、C4.5和C5.0创建决策树模型进行判断哪种模型更合适
data(churn)导入自带的训练集churnTrain和测试集churnTest 用id3.cart.C4.5和C5.0创建决策树模型,并用交叉矩阵评估模型,针对churn数据,哪种模型更合适 决 ...
- xshell上windows和linux互传文件命令
1.安装lrzsz包: yum install -y lrzsz 2.从windows上传文件到linux服务器: rz 会弹出选择文件窗口,按照提示做就行3.从linux服务器下载文件到本地的win ...
- go GTK msys2
1 下载安装msys2 MSYS2 (Minimal SYStem 2) 是一个MSYS的独立改写版本,主要用于 shell 命令行开发环境.同时它也是一个在Cygwin (POSIX 兼容性层) 和 ...
- spark 笔记 2: Resilient Distributed Datasets: A Fault-Tolerant Abstraction for In-Memory Cluster Computing
http://www.cs.berkeley.edu/~matei/papers/2012/nsdi_spark.pdf ucb关于spark的论文,对spark中核心组件RDD最原始.本质的理解, ...
- redis哨兵集群搭建
下载redis jar包redis-4.0.11.tar.gz放在/data/redis目录下 解压 命令:tar -zxvf redis-4.0.11.tar.gz 解压后如图所示 在/usr/lo ...
- java随机读取文件
package split; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStr ...