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灵活。因此也只是在特定的场景下使用。

java原生开发是什么意思_什么是ABA问题?java里面的原生解决方案是什么?原理是什么?...相关推荐

  1. java坦克大战 实训报告_坦克大战系统《Java程序开发实训》综合实训报告.doc

    坦克大战系统<Java程序开发实训>综合实训报告 <Java程序开发实训>综合实训报告 题目: 坦克大战系统 姓名: 方庆 学号: 2010203206 班级: 10软件(2) ...

  2. java获取当月有几天_你真的能在JAVA开发这条路上面一直坚持下去吗?

    JAVA为什么有前途? 过去的十多年,JAVA基本每年都是全世界使用人数第一的语言.全世界数百万的IT企业构建了庞大的JAVA生态圈,大量的软件基于JAVA开发. JAVA也被誉为"计算机界 ...

  3. 前端 python java三者哪个比较容易就业_前端和后端(Java)开发哪个难?,哪个学习容易一点?...

    关于前端和后端java学习难以程度,以下是我的分享. 难易程度: web前端开发 起点低.容易入门,相对于Java来说,前端对于逻辑思维的要求比较低,所以学习前端也要容易一些,所以你不用担心学不会.很 ...

  4. java网站开发模式有哪些_第7章JavaWeb常用开发模式.ppt

    第7章JavaWeb常用开发模式.ppt 7.4.4 JSP+Servlet+JavaBean案例 --学生体质信息管理系统 [例7-10]采用JSP+Servlet+JavaBean+JDBC+My ...

  5. java后端开发需要学什么_从事Java后端开发,要学习哪些知识和技能?

    首先要明确后端包括哪些职业:DBA(数据库维护优化专家),Developer(程序猿),Architect(构架师),Scrum master及类似(敏捷开发专家),Project Manager(产 ...

  6. java比较炫的小程序_有人不建议学Java,有人不建议学Python,该怎么选择

    首先,编程语言都有自己所特定的应用场景,不同的编程语言有不同的优势,同样也会有相应的缺点,所以程序员往往需要掌握多门编程语言,以应对不同的开发场景.虽然Java和Python都属于全场景编程语言,但是 ...

  7. java洗衣店管理课程设计报告_课内资源 - 基于Java的洗衣店管理系统

    摘 要 随着科技的快速发展,人们的需求也是越来越多,为了方便对信息的管理我们小组就设计了一个洗衣店订单的管理系统. 洗衣店管理系统是典型的的信息管理系统,创建了六个类,分别是:Test类:Person ...

  8. java中build是什么意思_科普 eclipse中的Java build

    在刚学eclipse的时候,build path是经常会用到的,但经常就是跟着教程走,额就不太懂这是干嘛的,然后今天看见极客视频里有相关的讲解,来记录一下. Build Path 是指定Java工程所 ...

  9. java里class有什么用_安装JDK时的java和javac命令有什么用?

    相信大家都装过JDK吧,在装JDK时我们会在命令提示符窗口中通过java和javac两个命令来检测我们的环境变量是否配置正确,那么你知道java和javac两个命令有什么用吗? 在了解这两个命令的作用 ...

最新文章

  1. R语言ggplot2可视化:为箱图的均值进行连线、将多个分组的均值连接起来Joining means on a boxplot with a line
  2. 【rnnoise源码分析】compute_frame_feature函数
  3. Linux多线程编程四(条件变量)
  4. Oracle AWR 介绍
  5. Python可视化中的Matplotlib(5.直方图、条形图以及饼图的用法和详细的参数)
  6. 牛客网Java刷题知识点之插入排序(直接插入排序和希尔排序)、选择排序(直接选择排序和堆排序)、冒泡排序、快速排序、归并排序和基数排序(博主推荐)...
  7. thymeleaf与jsp_PagingAndSortingRepository –如何与Thymeleaf一起使用
  8. 5G、IoT 时代下,手机聚焦拍照是否走错了方向?
  9. 动手写个数字输入框2:起手式——拦截非法字符
  10. kitkat(KRT16S)从hal层到app层写法
  11. Hive窗口函数的使用
  12. Windows安全配置
  13. 《老路用得上的商学课》61-65学习笔记
  14. 九宫格,二十五宫格,甚至八十一宫格 技巧
  15. cad字体安装_如何使用CAD插件与字体?1分钟掌握安装教程,让你快人一步!
  16. 气传导耳机是什么原理?气传导蓝牙耳机优缺点分析
  17. Makefile的最后一点问题也解决了
  18. 直流有刷电机控制原理及工程问题记录
  19. 美通企业周刊 | 中国平安将深度参与深圳公共住房建设;北京环球度假区将引入IMAX影院...
  20. 77岁老爷爷6次考研,老爷爷考的这所学校你敢考吗?

热门文章

  1. 安装微信开发者工具及创建小程序
  2. 图像边缘检测经典算子及MATLAB实现
  3. 南极区域点坐标单位由decimal degrees到meter转换
  4. 高度塌陷以及解决方法
  5. Java - 调用 Shell 命令和脚本
  6. 《炬丰科技-半导体工艺》减少化学品使用的清洁优化
  7. 婚恋职场人格-张晓文-武汉理工大学-中国MOOC-人格知识大比武测试题参考答案
  8. Cisco Packet Tracer 6.0下载安装及汉化包使用方法无积分版
  9. 【MacBookPro M1 安装Docker】
  10. 抖音测试脸是什么软件,抖音挺火的人脸渐渐变成狗脸,这个软件是什么