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显示的时候有时候 ...
随机推荐
- Invalid [xxx] in servlet mapping 、 <url-pattern>的匹配规则 、 DefaultServlet介绍
真的是很容易被忽视的错误,servlet 配置url的时候遇到问题,这个之前确实没有详细了解过. 出现这个错误的时候往往伴随着一系列高大上的错误,比如会出现类似[StandardEngine[Cata ...
- windows10禁止系统更新
- jquery dblclick()方法 语法
jquery dblclick()方法 语法 作用:当双击元素时,会发生 dblclick 事件.当鼠标指针停留在元素上方,然后按下并松开鼠标左键时,就会发生一次 click.在很短的时间内发生两次 ...
- react 的className动态修改
https://blog.csdn.net/suwyer/article/details/81481507(copy) <div style={{display: (index===this.s ...
- 翻页的时候更改URL地址
要求点击第一页是url+p1html,点击第二页是url+p2html等等 $("body").on('click','#w_tagPage a[wid]',function(){ ...
- hdu_1712(dp,背包)
hdu_1712 \[dp[i][j]\] 表示前i个物品用了j天得到的最大收益 \[ dp[i][j] = max(dp[i-1][j],dp[i][j-k]+ k*v[i][k]) \qquad ...
- python生成手机号
""" 电信号段:133/153/180/181/189/177; 联通号段:130/131/132/155/156/185/186/145/175; 移动号段:134/ ...
- 原生Js_实现简单选项卡功能
javascript实现选项卡功能,在<script>...</script>中编写代码 实现步骤 a)获得各操作的dom对象: b)在所有按钮对象上添加单击事件: c)设置所 ...
- akka 的集群访问方式
akka 中采用startProxy分区代理 访问 ,跟使用shardRegion 来访问的区别 这两种访问方式是不是重了呢. 而另外这是一个单例代理 private fun startUniver ...
- vultr云主机充10美元送50美元
目录 注册地址: 如何收费? 停止状态的实例是否收费? 有哪些支付方式? 提供哪些操作系统? 注册地址: https://www.vultr.com/?ref=8199131 如何收费? 按小时计费, ...