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详解相关推荐

  1. tcp out of order解决_Java解决CAS机制中ABA问题的方案

    通过对atomic包的分析我们知道了CAS机制,我们在看一下CAS的公式. CAS(V,A,B)1:V表示内存中的地址2:A表示预期值3:B表示要修改的新值 CAS的原理就是预期值A与内存中的值相比较 ...

  2. Java解决CAS机制中ABA问题的方案

    [原创] 强哥Java架构之路 2019-05-26 07:00:00 通过对atomic包的分析我们知道了CAS机制,我们在看一下CAS的公式. CAS(V,A,B) 1:V表示内存中的地址 2:A ...

  3. mysql解决aba问题_AtomicStampedReference解决CAS的ABA问题

    AtomicStampReference > 解决CAS的ABA问题 什么是ABA > ABA问题:指CAS操作的时候,线程将某个变量值由A修改为B,但是又改回了A,其他线程发现A并未改变 ...

  4. android 清理缓存动画,Android仿微信清理内存图表动画(解决surfaceView屏幕闪烁问题)demo实例详解...

    最近接了一个项目其中有功能要实现一个清理内存,要求和微信的效果一样.于是想到用surfaceView而不是继承view.下面小编给大家解析下实现思路. surfaceView是为了解决频繁绘制动画产生 ...

  5. CAS机制中的ABA问题

    在进行CAS操作的时候,会检查值有没有发生变化.如果没有变化则更新.如果发生变化了,则进行自旋. 但是有种情况是,预期的值看似没有变化,但是实际上的确变化了,例如原来的值是A,后来变成了B,最后又变成 ...

  6. ABAQUS有限元仿真计算工作站单机多核/多机多核集群硬件配置详解

    ABAQUS有限元软件用于分析复杂的固体力学.结构力学系统,特别是庞大复杂的问题和模拟高度非线性问题:其解决问题的范围从相对简单的线性分析到许多复杂的非线性问题.作为通用的模拟工具, ABAQUS 除 ...

  7. Xcode真机调试(无需证书)详解

    首先准备: 1.xcode 更新到7以上:MacOS更新到10.11以上: 2. 自己有一个app id  也就是能登陆app store 的账号: 第二步: 安装好MacOSX和VMWareTool ...

  8. STM32F103C8T6核心开发板下,采用串口DMA方式向上位机连续发送数据的实例详解

    STM32采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据 文章目录 STM32采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据 前言 一.DMA应用初步 ...

  9. CAS和ASQ原理(源码详解)

    前面介绍Java中的锁机制时简单介绍过CAS和ASQ,这篇文章则是进行详细的学习介绍. 一.CAS(CompareAndSwamp,比较并交换) 1.简介 CAS有3个操作数: 内存值V.预期值A.更 ...

最新文章

  1. 测试人员的GitHub
  2. UVa1346 - Songs(贪心算法)
  3. Leetcode264. Ugly Number II丑数2
  4. node process.env
  5. matlab gui自定义图片做背景,matlab GUI自定义图片做背景
  6. wxWidgets:wxThreadHelper类用法
  7. sublime text3支持Vue语法高亮显示步骤(转)
  8. php phpmailer qq邮箱,QQ邮箱利用PHPmailer发送邮件
  9. Maven之生成测试覆盖度的插件cobertura-maven-plugin的使用
  10. 如何在矩池云GPU云中跑DeepFaceLab
  11. 酒店管理系统java实现
  12. 最近碰到了一个病毒木马:virus.win32.ramnit.B
  13. 如何在电脑上录制qq语音
  14. 3 Robotics: Mobility 课程学习记录及课后习题解答
  15. 手机内存清理软件,让你的手机更轻更快!
  16. ElasticSearch 从5.6.3升级到7.9.3遇到问题总结
  17. pr使用视频素材技巧
  18. 用SQLite进行全文检索
  19. 9.2 常用缩写汇总表
  20. 关于Directx中shader的输入与输出

热门文章

  1. java技术全掌握了_你必须掌握的 21 个 Java 核心技术!
  2. cytoscape插件bingo使用
  3. JGG: 赵方庆、赵翔等开发高效捕获RNA病毒基因组的宏转录组建库测序新技术
  4. MPB:地大郭东毅等-一种针对重金属污染土壤的高效DNA提取方法
  5. SEL|世界土壤日-土壤生态学Nico Eisenhauer 教授讲座
  6. Genome Biology:人体各部位微生物组时间序列分析Moving Pictures
  7. SourceTracker—微生物来源分析
  8. Microbiome:肠道菌群失衡促进高血压
  9. R语言ggplot2可视化分面图(facet_wrap)、使用size参数自定义设置分面图标签栏(灰色标签栏)中的标签文本的字体大小
  10. R语言ggplot2可视化:使用ggplot2按照热力图的方式显示全是分类变量的dataframe数据、并自定义因子(factor)的图例颜色legend