java并发编程(6)--CAS会导致“ABA问题“ 解决方案
一、⾼频⾯试题
1. 原⼦类AtomicInteger的ABA问题谈谈?原⼦更新引⽤你知道吗?
2. 我们知道ArrayList是线程不安全,请编码写⼀个不安全的案例并给出解决⽅案
3. 公平锁/⾮公平锁/可重⼊锁/递归锁/⾃旋锁谈谈你的理解?请⼿写⼀个⾃旋锁
4. CountDownLath/CyclicBarrier/Semaphore使⽤过吗?
5. 阻塞队列知道吗?
6. 线程池⽤过吗?ThreadPoolExecutor谈谈你的理解?⽣产上你如何设置合理参数
7. 死锁编码及定位分析
二、ABA问题
所谓ABA问题,就是CAS算法实现需要取出内存中某时刻的数据并在当下时刻⽐较并替换,这⾥存在⼀ 个时间差,那么这个时间差可能带来意想不到的问题。
⽐如,⼀个线程B 从内存位置Value中取出2,这时候另⼀个线程A 也从内存位置Value中取出2,并且 线程A 进⾏了⼀些操作将值变成了5,然后线程A ⼜再次将值变成了2,这时候线程B 进⾏CAS操作发现 内存中仍然是2,然后线程B 操作成功。
尽管线程B 的CAS操作成功,但是不代表这个过程就是没有问题的。
有这样的需求,⽐如CAS,只注重头和尾,只要⾸尾⼀致就接受。
但是有的需求,还看重过程,中间不能发⽣任何修改,这就引出了 AtomicReference 原⼦引 ⽤。
三、AtomicReference原⼦引⽤
AtomicInteger对整数进⾏原⼦操作,如果是⼀个POJO呢?可以⽤AtomicReference来包装这个 POJO,使其操作原⼦化。
package thread;public class AtomicReferenceDemo {public static void main(String[] args) {User user1 = new User("Jack",25);User user2 = new User("Tom",21);AtomicReference<User> atomicReference = new AtomicReference<>();atomicReference.set(user1);System.out.println(atomicReference.compareAndSet(user1,user2)+"\t"+atomicReference.get()); // trueSystem.out.println(atomicReference.compareAndSet(user1,user2)+"\t"+atomicReference.get()); //false}
}
四、ABA问题的解决(AtomicStampedReference 类似于时间 戳)
ThreadA 100 1 2020 2ThreadB 100 1 111 2 100 3
使⽤AtomicStampedReference类可以解决ABA问题。
这个类维护了⼀个“版本号”Stamp,在进⾏CAS操作的时候,不仅要⽐较当前值,还要⽐较版本号。
只有两者都相等,才执⾏更新操作。
解决ABA问题的关键⽅法:
参数说明:
- V expectedReference, 预期值引⽤
- V newReference, 新值引⽤
- int expectedStamp, 预期值时间戳
- int newStamp, 新值时间戳
package thread;import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;public class ABADemo {static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1);public static void main(String[] args) {System.out.println("======ABA问题的产⽣======");// 100->101->100new Thread(() -> {atomicReference.compareAndSet(100, 101);atomicReference.compareAndSet(101, 100);}, "t1").start();// 100->2020new Thread(() -> {try {TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e) {e.printStackTrace();}System.out.println(atomicReference.compareAndSet(100, 2020) + "\t" + atomicReference.get().toString());}, "t2").start();try {TimeUnit.SECONDS.sleep(2);}catch (InterruptedException e) {e.printStackTrace();}System.out.println(" ======ABA问题的解决======");// 100(1)->101(2)->100(3)new Thread(() -> {int stamp = atomicStampedReference.getStamp();// t3 第⼀次 版本号: 1System.out.println(Thread.currentThread().getName() + "\t第⼀次 版本号: " + stamp);try {TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e) {e.printStackTrace();}//t3 第⼆次 版本号: 2atomicStampedReference.compareAndSet(100,101, atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1); System.out.println(Thread.currentThread().getName() + "\t第⼆次 版本号: " + atomicStampedReference.getStamp());//t3 第三次 版本号: 3atomicStampedReference.compareAndSet(101,100, atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1); System.out.println(Thread.currentThread().getName() + "\t第三次 版本号: " + atomicStampedReference.getStamp());}, "t3").start();//new Thread(() -> {int stamp = atomicStampedReference.getStamp();// stamp = 1// t4 第⼀次 版本号: 1System.out.println(Thread.currentThread().getName() + "\t第⼀次 版本号: " + stamp);try {TimeUnit.SECONDS.sleep(3);}catch (InterruptedException e) {e.printStackTrace();}boolean result=atomicStampedReference.compareAndSet(100,2020, stamp,stamp+1);// t4 修改成功 与否:false 当前最新版本号3System.out.println(Thread.currentThread().getName()+"\t修改成功 与否:"+result+" 当前最新版本号"+atomicStampedReference.getStamp());// t4 当前实际值:100System.out.println(Thread.currentThread().getName()+"\t当前实际值:"+atomicStampedReference.getReference());}, "t4").start();}}
java并发编程(6)--CAS会导致“ABA问题“ 解决方案相关推荐
- Java并发编程,无锁CAS与Unsafe类及其并发包Atomic
为什么80%的码农都做不了架构师?>>> 我们曾经详谈过有锁并发的典型代表synchronized关键字,通过该关键字可以控制并发执行过程中有且只有一个线程可以访问共享资源,其 ...
- Java 并发编程CAS、volatile、synchronized原理详解
CAS(CompareAndSwap) 什么是CAS? 在Java中调用的是Unsafe的如下方法来CAS修改对象int属性的值(借助C来调用CPU底层指令实现的): /*** * @param o ...
- Java并发编程-无锁CAS与Unsafe类及其并发包Atomic
[版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/72772470 出自[zejian ...
- JAVA并发编程学习笔记之CAS操作
http://blog.csdn.net/aesop_wubo/article/details/7537960 CAS操作 CAS是单词compare and set的缩写,意思是指在set之前先比较 ...
- JAVA并发编程: CAS和AQS
说起JAVA并发编程,就不得不聊聊CAS(Compare And Swap)和AQS了(AbstractQueuedSynchronizer). CAS(Compare And Swap) 什么是CA ...
- Java并发编程75道面试题及答案
1.在java中守护线程和本地线程区别?java中的线程分为两种:守护线程(Daemon)和用户线程(User).任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bo ...
- Java 并发编程-不懂原理多吃亏(送书福利)
作者 | 加多 关注阿里巴巴云原生公众号,后台回复关键字"并发",即可参与送书抽奖! ** 导读:并发编程与 Java 中其他知识点相比较而言学习门槛较高,从而导致很多人望而却步. ...
- java 并发编程总结
这边文章的主要内容是基于"java并发编程艺术"这本书,中间加入了一些自己的理解.这篇文章包括并发编程涉及到的几乎所有基础知识.主要是帮助长期从事业务逻辑开发的java程序员梳理一 ...
- Java并发编程—常见面试题
建议: 学习java并发前需要先掌握JVM知识 关于下面问题档案的详细解析都在后面推荐的相关系列文章中 一.线程安全相关 1.什么叫线程安全? 线程安全就是说多线程访问同一代码,不会产生不确定的结果. ...
- 干货:Java并发编程必懂知识点解析
本文大纲 1.并发编程三要素 原子性 原子,即一个不可再被分割的颗粒.在Java中原子性指的是一个或多个操作要么全部执行成功要么全部执行失败. 有序性 程序执行的顺序按照代码的先后顺序执行.(处理器可 ...
最新文章
- Java缓存学习之五:spring 对缓存的支持
- 【 FPGA 】FIR滤波器之 Hilbert 变换的实现
- c语言中的tanh函数,tanh()函数,用于C ++中的复数
- 低版本ulibc支持recvmmsg sendmmsg功能
- JavaScript回调函数(callback)概念和应用,千万别错过!
- mysql8双机热备高可用配置
- JVM参数调优详细过程
- 红橙Darren视频笔记 状态栏设置颜色 获取高度 设置全屏
- 华北水利水电大学c语言实验报告八2020,2021年华北水利水电大学级C语言实验报告.doc...
- java积分签到功能_对于签到功能的一点理解
- plsql连接不上64位oracle,PLSQL Developer 不能连接 64位 Oracle 11g 的解决办法
- FFmpeg拼接文件常见问题
- 风险分析(Barra风险模型)
- windows XP下openbravo ERP 2.40安装手迹
- 【基础知识】8、加州房价预测项目精细解释
- 如何合理布局浏览器网页!
- SQLSERVER 数据库或表修复(DBCC CHECKDB)
- 把握SDN研发方向,展望未来发展趋势
- Java实现蓝桥杯勇者斗恶龙
- windows双屏显示如何设置