李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
Java
正文
CAS的ABA问题及解决
Leefs
2020-02-22 PM
1525℃
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
标签云
JVM
Python
CentOS
Filter
Git
高并发
Golang
FastDFS
VUE
序列化和反序列化
微服务
并发线程
Java工具类
Jquery
国产数据库改造
SpringBoot
Livy
Kibana
BurpSuite
RSA加解密
队列
Spark Core
NIO
持有对象
锁
HDFS
SQL练习题
Map
Java
Ubuntu
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞