aba问题mysql_解决CAS机制中ABA问题的AtomicStampedReference详解
AtomicStampedReference是一个带有时间戳的对象引用,能很好的解决CAS机制中的ABA问题,这篇文章将通过案例对其介绍分析。
一、ABA问题
ABA问题是CAS机制中出现的一个问题,他的描述是这样的。我们直接画一张图来演示,
什么意思呢?就是说一个线程把数据A变为了B,然后又重新变成了A。此时另外一个线程读取的时候,发现A没有变化,就误以为是原来的那个A。这就是有名的ABA问题。ABA问题会带来什么后果呢?我们举个例子。一个小偷,把别人家的钱偷了之后又还了回来,还是原来的钱吗,你老婆出轨之后又回来,还是原来的老婆嘛?ABA问题也一样,如果不好好解决就会带来大量的问题。最常见的就是资金问题,也就是别人如果挪用了你的钱,在你发现之前又还了回来。但是别人却已经触犯了法律。
如何去解决这个ABA问题呢,就是使用今天所说的AtomicStampedReference。
二、AtomicStampedReference
1、问题解决
我们先给出一个ABA的例子,对ABA问题进行场景重现。public class AtomicTest{
private static AtomicInteger index = new AtomicInteger(10);
public static void main(String[] args){
new Thread(() -> {
index.compareAndSet(10, 11);
index.compareAndSet(11, 10);
System.out.println(Thread.currentThread().getName()+
":10->11->10");
},"张三").start();
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
boolean isSuccess = index.compareAndSet(10, 12);
System.out.println(Thread.currentThread().getName()+
":index是预期的10嘛,"+isSuccess
+" 设置的新值是:"+index.get());
} catch (InterruptedException e) {
e.printStackTrace();
}
},"李四").start();
}
}
在上面的代码中,我们使用张三线程,对index10->11->10的变化,然后李四线程读取index观察是否有变化,并设置新值。运行一下看看结果:
这个案例重现了ABA的问题场景,下面我们看如何使用AtomicStampedReference解决这个问题的。public class AtomicTest2{
private static AtomicInteger index = new AtomicInteger(10);
static AtomicStampedReference stampRef
= new AtomicStampedReference(10, 1);
public static void main(String[] args){
new Thread(() -> {
int stamp = stampRef.getStamp();
System.out.println(Thread.currentThread().getName()
+ " 第1次版本号: " + stamp);
stampRef.compareAndSet(10, 11,stampRef.getStamp(),stampRef.getStamp()+1);
System.out.println(Thread.currentThread().getName()
+ " 第2次版本号: " + stampRef.getStamp());
stampRef.compareAndSet(11, 10,stampRef.getStamp(),stampRef.getStamp()+1);
System.out.println(Thread.currentThread().getName()
+ " 第3次版本号: " + stampRef.getStamp());
},"张三").start();
new Thread(() -> {
try {
int stamp = stampRef.getStamp();
System.out.println(Thread.currentThread().getName()
+ " 第1次版本号: " + stamp);
TimeUnit.SECONDS.sleep(2);
boolean isSuccess =stampRef.compareAndSet(10, 12,
stampRef.getStamp(),stampRef.getStamp()+1);
System.out.println(Thread.currentThread().getName()
+ " 修改是否成功: "+ isSuccess+" 当前版本 :" + stampRef.getStamp());
System.out.println(Thread.currentThread().getName()
+ " 当前实际值: " + stampRef.getReference());
} catch (InterruptedException e) {
e.printStackTrace();
}
},"李四").start();
}
}
上面的代码我们再来分析一下,我们会发现AtomicStampedReference里面增加了一个时间戳,也就是说每一次修改只需要设置不同的版本好即可。我们先运行一边看看:
这使用的是AtomicStampedReference的compareAndSet函数,这里有四个参数:
compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp)。
(1)第一个参数expectedReference:表示预期值。
(2)第二个参数newReference:表示要更新的值。
(3)第三个参数expectedStamp:表示预期的时间戳。
(4)第四个参数newStamp:表示要更新的时间戳。
这个compareAndSet方法到底是如何实现的,我们深入到源码中看看。
2、源码分析public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp){
Pair current = pair;
return
expectedReference == current.reference &&
expectedStamp == current.stamp &&
((newReference == current.reference &&
newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp)));
}
刚刚这四个参数的意思已经说了,我们主要关注的就是实现,首先我们看到的就是这个Pair,因此想要弄清楚,我们再看看这个Pair是什么,private static class Pair{
final T reference;
final int stamp;
private Pair(T reference, int stamp){
this.reference = reference;
this.stamp = stamp;
}
static Pair of(T reference, int stamp){
return new Pair(reference, stamp);
}
}
在这里我们会发现Pair里面只是包存了值reference和时间戳stamp。
在compareAndSet方法中最后还调用了casPair方法,从名字就可以看到,主要是使用CAS机制更新新的值reference和时间戳stamp。我们可以进入这个方法中看看。//底层调用的是UNSAFE的compareAndSwapObject方法
private boolean casPair(Pair cmp, Pair val){
return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
}
三、总结
其实除了AtomicStampedReference类,还有一个原子类也可以解决,就是AtomicMarkableReference,它不是维护一个版本号,而是维护一个boolean类型的标记,用法没有AtomicStampedReference灵活。因此也只是在特定的场景下使用。
aba问题mysql_解决CAS机制中ABA问题的AtomicStampedReference详解相关推荐
- tcp out of order解决_Java解决CAS机制中ABA问题的方案
通过对atomic包的分析我们知道了CAS机制,我们在看一下CAS的公式. CAS(V,A,B)1:V表示内存中的地址2:A表示预期值3:B表示要修改的新值 CAS的原理就是预期值A与内存中的值相比较 ...
- Java解决CAS机制中ABA问题的方案
[原创] 强哥Java架构之路 2019-05-26 07:00:00 通过对atomic包的分析我们知道了CAS机制,我们在看一下CAS的公式. CAS(V,A,B) 1:V表示内存中的地址 2:A ...
- mysql解决aba问题_AtomicStampedReference解决CAS的ABA问题
AtomicStampReference > 解决CAS的ABA问题 什么是ABA > ABA问题:指CAS操作的时候,线程将某个变量值由A修改为B,但是又改回了A,其他线程发现A并未改变 ...
- android 清理缓存动画,Android仿微信清理内存图表动画(解决surfaceView屏幕闪烁问题)demo实例详解...
最近接了一个项目其中有功能要实现一个清理内存,要求和微信的效果一样.于是想到用surfaceView而不是继承view.下面小编给大家解析下实现思路. surfaceView是为了解决频繁绘制动画产生 ...
- CAS机制中的ABA问题
在进行CAS操作的时候,会检查值有没有发生变化.如果没有变化则更新.如果发生变化了,则进行自旋. 但是有种情况是,预期的值看似没有变化,但是实际上的确变化了,例如原来的值是A,后来变成了B,最后又变成 ...
- ABAQUS有限元仿真计算工作站单机多核/多机多核集群硬件配置详解
ABAQUS有限元软件用于分析复杂的固体力学.结构力学系统,特别是庞大复杂的问题和模拟高度非线性问题:其解决问题的范围从相对简单的线性分析到许多复杂的非线性问题.作为通用的模拟工具, ABAQUS 除 ...
- Xcode真机调试(无需证书)详解
首先准备: 1.xcode 更新到7以上:MacOS更新到10.11以上: 2. 自己有一个app id 也就是能登陆app store 的账号: 第二步: 安装好MacOSX和VMWareTool ...
- STM32F103C8T6核心开发板下,采用串口DMA方式向上位机连续发送数据的实例详解
STM32采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据 文章目录 STM32采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据 前言 一.DMA应用初步 ...
- CAS和ASQ原理(源码详解)
前面介绍Java中的锁机制时简单介绍过CAS和ASQ,这篇文章则是进行详细的学习介绍. 一.CAS(CompareAndSwamp,比较并交换) 1.简介 CAS有3个操作数: 内存值V.预期值A.更 ...
最新文章
- 测试人员的GitHub
- UVa1346 - Songs(贪心算法)
- Leetcode264. Ugly Number II丑数2
- node process.env
- matlab gui自定义图片做背景,matlab GUI自定义图片做背景
- wxWidgets:wxThreadHelper类用法
- sublime text3支持Vue语法高亮显示步骤(转)
- php phpmailer qq邮箱,QQ邮箱利用PHPmailer发送邮件
- Maven之生成测试覆盖度的插件cobertura-maven-plugin的使用
- 如何在矩池云GPU云中跑DeepFaceLab
- 酒店管理系统java实现
- 最近碰到了一个病毒木马:virus.win32.ramnit.B
- 如何在电脑上录制qq语音
- 3 Robotics: Mobility 课程学习记录及课后习题解答
- 手机内存清理软件,让你的手机更轻更快!
- ElasticSearch 从5.6.3升级到7.9.3遇到问题总结
- pr使用视频素材技巧
- 用SQLite进行全文检索
- 9.2	常用缩写汇总表
- 关于Directx中shader的输入与输出
热门文章
- java技术全掌握了_你必须掌握的 21 个 Java 核心技术!
- cytoscape插件bingo使用
- JGG: 赵方庆、赵翔等开发高效捕获RNA病毒基因组的宏转录组建库测序新技术
- MPB:地大郭东毅等-一种针对重金属污染土壤的高效DNA提取方法
- SEL|世界土壤日-土壤生态学Nico Eisenhauer 教授讲座
- Genome Biology:人体各部位微生物组时间序列分析Moving Pictures
- SourceTracker—微生物来源分析
- Microbiome:肠道菌群失衡促进高血压
- R语言ggplot2可视化分面图(facet_wrap)、使用size参数自定义设置分面图标签栏(灰色标签栏)中的标签文本的字体大小
- R语言ggplot2可视化:使用ggplot2按照热力图的方式显示全是分类变量的dataframe数据、并自定义因子(factor)的图例颜色legend