AtomicStampedReference AtomicReference解决CAS机制中ABA问题

AtomicStampedReference

AtomicStampedReference它内部不仅维护了对象值,还维护了一个版本号(可以是任何一个整数,它使用整数来表示状态值)。当AtomicStampedReference对应的数值被修改时,除了更新数据本身外,还必须要更新版本号。因此只要版本号发生变化,就能防止不恰当的写入。版本号类似于时间戳。

  1. import java.util.concurrent.atomic.AtomicInteger;
  2. import java.util.concurrent.atomic.AtomicStampedReference;
  3. public class Test {
  4. /**
  5. **/
  6. public static void main(String[] args) {
  7. AtomicInteger integer = new AtomicInteger(0);
  8. AtomicStampedReference<Integer> reference = new AtomicStampedReference<>(100,1000);
  9. Thread t1 = new Thread(new Runnable() {
  10. @Override
  11. public void run() {
  12. integer.compareAndSet(0,1);
  13. integer.compareAndSet(1,0);
  14. }
  15. });
  16. Thread t2 = new Thread(new Runnable() {
  17. @Override
  18. public void run() {
  19. try {
  20. Thread.currentThread().sleep(1000);
  21. } catch (InterruptedException e) {
  22. e.printStackTrace();
  23. }
  24. boolean b = integer.compareAndSet(0, 1);
  25. System.out.println("AtomicInteger替换");
  26. if(b) System.out.println("0已经被替换为1");
  27. else System.out.println("替换失败");
  28. }
  29. });
  30. Thread t3 = new Thread(new Runnable() {
  31. @Override
  32. public void run() {
  33. try {
  34. Thread.currentThread().sleep(1000);
  35. } catch (InterruptedException e) {
  36. e.printStackTrace();
  37. }
  38. reference.compareAndSet(100,-100,
  39. reference.getStamp(), reference.getStamp()+1);
  40. reference.compareAndSet(-100,100,
  41. reference.getStamp(), reference.getStamp()+1);
  42. }
  43. });
  44. Thread t4 = new Thread(new Runnable() {
  45. @Override
  46. public void run() {
  47. int stamp = reference.getStamp();
  48. try {
  49. Thread.currentThread().sleep(2000);
  50. } catch (InterruptedException e) {
  51. e.printStackTrace();
  52. }
  53. boolean b = reference.compareAndSet(100, -100,
  54. stamp, reference.getStamp() + 1);
  55. System.out.println("AtomicStampedReference替换");
  56. if(b) System.out.println("100已经被替换为-100");
  57. else System.out.println("替换失败");
  58. }
  59. });
  60. t1.start();
  61. t2.start();
  62. t3.start();
  63. t4.start();
  64. }
  65. }
  66. 输出结果:
  67. AtomicInteger替换
  68. 0已经被替换为1
  69. AtomicStampedReference替换
  70. 替换失败

AtomicReference

AtomicReference类提供了一个可以原子读写的对象引用变量。 原子意味着尝试更改相同AtomicReference的多个线程(例如,使用比较和交换操作)不会使AtomicReference最终达到不一致的状态。

  1. import java.util.concurrent.atomic.AtomicReference;
  2. public class ABAObjectTest {
  3. public static void main(String[] args) {
  4. SubObject subObject = new SubObject(100,"一百");
  5. AtomicReference<SubObject> reference = new AtomicReference<>(subObject);
  6. SubObject subObject1 = new SubObject(200,"二百");
  7. SubObject subObject2 = new SubObject(300,"三百");
  8. Thread t1 = new Thread(new Runnable() {
  9. @Override
  10. public void run() {
  11. boolean b = reference.compareAndSet(subObject, subObject1);
  12. SubObject object = reference.get();
  13. System.out.println(b);
  14. System.out.println(object);
  15. }
  16. });
  17. Thread t2 = new Thread(new Runnable() {
  18. @Override
  19. public void run() {
  20. try {
  21. Thread.currentThread().sleep(1000);
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. System.out.println("=============");
  26. System.out.println(reference.get());
  27. boolean b = reference.compareAndSet(subObject, subObject2);
  28. System.out.println(b);
  29. System.out.println(reference.get());
  30. }
  31. });
  32. t1.start();
  33. t2.start();
  34. }
  35. }
  36. /*输出结果:
  37. true
  38. SubObject{intNum=200, string='二百'}
  39. =============
  40. SubObject{intNum=200, string='二百'}
  41. false
  42. SubObject{intNum=200, string='二百'}*/
  43. class SubObject {
  44. public int intNum;
  45. public String string;
  46. public int getIntNum() {
  47. return intNum;
  48. }
  49. public void setIntNum(int intNum) {
  50. this.intNum = intNum;
  51. }
  52. public String getString() {
  53. return string;
  54. }
  55. public void setString(String string) {
  56. this.string = string;
  57. }
  58. public SubObject(int intNum, String string) {
  59. this.intNum = intNum;
  60. this.string = string;
  61. }
  62. public SubObject() {
  63. }
  64. @Override
  65. public String toString() {
  66. return "SubObject{" +
  67. "intNum=" + intNum +
  68. ", string='" + string + '\'' +
  69. '}';
  70. }
  71. }

AtomicStampedReference AtomicReference解决CAS机制中ABA问题的更多相关文章

  1. 基于CAS分析对ABA问题的一点思考

    基于CAS分析对ABA问题的一点思考 什么是CAS? 背景 synchronized加锁消耗太大 volatile只保证可见性,不保证原子性 基础 用CPU提供的特殊指令,可以: 自动更新共享数据; ...

  2. Java 反照机制中 getMethod()和getDeclaredField()区别

    Java 反射机制中 getMethod()和getDeclaredField()区别 今天在程序中用到java反射机制时,遇到的问题记录一下:我当时遇到的问题是,我用反射getMethod()调用类 ...

  3. 解决服务器复制中SID冲突问题

    解决服务器复制中SID冲突问题 如果你有多部的主机需要安装,最快的方法是什么?想必就是用像GHOST之类的软件来进行硬盘的复制.当然,如果是安装在虚拟机之中,则需要复制虚拟的硬盘档案即可,以微软的VP ...

  4. MySQL InnoDB 日志管理机制中的MTR和日志刷盘

    1.MTR(mini-transaction) 在MySQL的 InnoDB日志管理机制中,有一个很重要的概念就是MTR.MTR是InnoDB存储擎中一个很重要的用来保证物理写的完整性和持久性的机制. ...

  5. dubbo源码分析2——SPI机制中的SPI实现类的读取和预处理

    SPI机制中的SPI实现类的读取和预处理是由ExtensionLoader类的loadFile方法来完成的 loadFile方法的作用是读取dubbo的某个SPI接口的spi描述文件,然后进行缓存,缓 ...

  6. java多线程机制中的Thread和Runnable()区别

    1.java语言使用Thread类及其子类对象来表示线程,新建的一个线程声明周期中经历 新建.(声明一个线程,此时他已经有了相应的内存空间和其他资源),运行(线程创建之久就据用了运行的条件,一旦轮到使 ...

  7. Linux内存管理机制中buffer和cache的区别

    Linux内存管理机制中buffer和cache的区别理解linux内存管理,需要深入了解linux内存的各个参数含义和规则,下面介绍一下Linux操作系统中内存buffer和cache的区别. Fr ...

  8. CAS导致的ABA问题及解决:时间戳原子引用AtomicReference、AtomicStampedReference

    1.CAS导致ABA问题: CAS算法实现一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并交换,那么在这个时间差中会导致数据的变化. 比如:线程1从内存位置V中取出A,这时线程2也从V中取出A ...

  9. JUC 并发编程--05, Volatile关键字特性: 可见性, 不保证原子性,禁止指令重排, 代码证明过程. CAS了解么 , ABA怎么解决, 手写自旋锁和死锁

    问: 了解volatile关键字么? 答: 他是java 的关键字, 保证可见性, 不保证原子性, 禁止指令重排 问: 你说的这三个特性, 能写代码证明么? 答: .... 问: 听说过 CAS么 他 ...

随机推荐

  1. ifix vba 读取计算机中的txt文件,截取字符串显示

    利用vba脚本,使用Scripting.FileSystemObject对象可以实现对文本文件的操作,下面以一个朋友的实际例子为例将截获的字符串进行页面显示. Private Sub CommandB ...

  2. css文件编码

    当css文件的编码

  3. 三年Android开发快手、美团、支付宝连挂,怒刷1549页面试题字节上岸

    刚开始面试的时候我真的是处处碰壁,面一家挂一家,面完之后怀疑自我,是不是自己真的太菜了找不到工作.工作本身就是双向选择,一家不行再换一家,总有合适的,千万不要因为别人的一句话就全盘否定自己,一定要自信 ...

  4. CentOS后台服务管理类

    目录 一.service 后台服务管理(临时,只对当前有效) 二.chkconfig 设置后台服务的自启配置(永久) 三.CentOS7 后添加的命令:systemctl 一.service 后台服务 ...

  5. 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(11.B)- FlexSPI NOR连接方式大全(RT1160/1170)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MXRT1160/1170两款MCU的FlexSPI NOR启动的连接方式. 这个 i.MXRT FlexSPI NOR 启动 ...

  6. 跟我一起写 Makefile(十)

    四.foreach 函数 foreach函数和别的函数非常的不一样.因为这个函数是用来做循环用的,Makefile中的foreach函数几乎是仿照于Unix标准Shell(/bin/sh)中的for语 ...

  7. E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable) E: Unable to lock the administration directory (/var/lib/dpkg/), is another process using it?

    E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable)E: Unable to l ...

  8. Django ORM多表查询

    基于双下划线查询 根据存的时候,字段的数据格式衍生的查询方法 1.年龄大于35岁 res = models.AuthorDetails.objects.filter(age__lt=80) print ...

  9. Android 9.0 默认输入法的设置流程分析

    Android 输入法设置文章 Android 9.0 默认输入法的设置流程分析 Android 9.0 添加预置第三方输入法/设置默认输入法(软键盘) 前言 在上一篇文章  Android 9.0 ...

  10. NOIP 模拟 $24\; \rm matrix$

    题解 \(by\;zj\varphi\) 发现 \(\rm n,m\) 都很小,考虑分行状压. 但是上一行和下一行的按钮状态会对当前行造成影响,所以再枚举一个上一行的按钮状态. 因为对于两行,只有如下 ...