李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
Java
正文
CAS的ABA问题及解决
Leefs
2020-02-22 PM
2092℃
0条
# CAS的ABA问题及解决 问题描述:当获得对象当前数据后,在准备修改为新值前,对象的值被其他线程连续修改了两次,而经过两次修改后,对象的值又恢复为旧值,这样当前线程无法确定判断这个对象是否修改过。 解决方法:JDK1.5可以利用**AtomicStampedReference**类来解决这个问题,AtomicStampedReference内部**不仅维护了对象值,还维护了一个时间戳。**当AtomicStampedReference对应的数值被修改过,除了更新数据本身外,还必须要更新时间戳,对象值和时间戳都必须满足期望值,写入才会成功 **代码实现** ```java public class ABADemo { private static AtomicReference
atomicReference = new AtomicReference<>(100); private static AtomicStampedReference
stampedReference = new AtomicStampedReference<>(100,1); public static void main(String[] args) { System.out.println("====ABA问题的产生==="); new Thread(()->{ atomicReference.compareAndSet(100,101); atomicReference.compareAndSet(101,100); },"t1").start(); new Thread(()->{ //先暂停1秒,保证完成ABA try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(atomicReference.compareAndSet(100, 2019)+"\t"+atomicReference.get()); },"t2").start(); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("===ABA问题的解决==="); new Thread(()->{ int stamp = stampedReference.getStamp(); System.out.println(Thread.currentThread().getName()+"\t 第1次版本号"+stamp+"\t值是"+stampedReference.getReference()); ///暂停1秒钟t3线程 try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } stampedReference.compareAndSet(100,101,stampedReference.getStamp(),stampedReference.getStamp()+1); System.out.println(Thread.currentThread().getName()+"\t 第2次版本号"+stampedReference.getStamp()+"\t值是"+stampedReference.getReference()); stampedReference.compareAndSet(101,100,stampedReference.getStamp(),stampedReference.getStamp()+1); System.out.println(Thread.currentThread().getName()+"\t 第3次版本号"+stampedReference.getStamp()+"\t值是"+stampedReference.getReference()); },"t3").start(); new Thread(()->{ int stamp = stampedReference.getStamp(); System.out.println(Thread.currentThread().getName()+"\t 第1次版本号"+stamp+"\t值是"+stampedReference.getReference()); //保证线程3完成1次ABA try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } boolean result = stampedReference.compareAndSet(100, 2019, stamp, stamp + 1); System.out.println(Thread.currentThread().getName()+"\t 修改成功否"+result+"\t最新版本号"+stampedReference.getStamp()); System.out.println("最新的值\t"+stampedReference.getReference()); },"t4").start(); } } ``` **代码运行结果** ```java ====ABA问题的产生=== true 2019 ===ABA问题的解决=== t3 第1次版本号1 值是100 t4 第1次版本号1 值是100 t3 第2次版本号2 值是101 t3 第3次版本号3 值是100 t4 修改成功否false 最新版本号3 最新的值 100 ```
标签:
Java
,
并发编程
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/638.html
上一篇
CAS简介
下一篇
集合类不安全之并发修改异常
评论已关闭
栏目分类
随笔
2
Java
326
大数据
229
工具
31
其它
25
GO
47
NLP
4
标签云
Jenkins
Netty
国产数据库改造
排序
Python
容器深入研究
SpringBoot
Golang基础
JavaSE
微服务
Map
JVM
字符串
链表
Spark Core
前端
MyBatis
Livy
Spark
Golang
Flink
Elastisearch
MyBatis-Plus
DataX
Quartz
Stream流
Spark RDD
哈希表
Hive
Java工具类
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞
评论已关闭