java_CAS
1.Java_第一季_JAVASE_自增、单例模式、类与实例初始化过程、方法参数传递机制、递归和迭代、成员变量与局部变量2.Java_第一季_SSM_Spring Bean的作用域、Spring事务的传播行为、Spring MVC的执行流程、3.Java_第一季_java高级_Redis持久化、MySql何时建立索引4.java_JUC、volatile
5.java_CAS
6.java_阻塞队列(FIFO先进先出)7.JUC下countDownLatch、CyclicBarrier、Semaphore以及枚举的常见使用方法8.java_锁9.java_集合不安全10.Spring循环依赖11.AbstractQueuedSynchronizer---AQS12.LockSuport13.java_线程池7大参数_底层运行原理14.java_线程池三个常用方式15.Java_Callable<V>的基本使用16.java_锁_synchronized与Lock的区别17.java_强、软、弱、虚四大引用18.java_OOM19.JAVA-interview20.java_NIO21.java_JVM之GC22.java_JVM23.单例模式设计24.netty服务端、客户端简单搭建25.java使用webSocket与前端通讯26.java串口通讯27.用Java读取文件文字并语音播报28.Proguard-混淆29.Spring Security30.MQ31.spring相关面试题32.执行jar包33.Spring34.SpringBoot数据访问35.Java Stream(流)基本使用36.java集合工具类 Collections基本使用37.LocalDateTime、LocalDate、Date、String相互转化38.java8新特性39.java设计模式40.java springboot使用定时器41.MQ根据正常队列、死信队列来实现延迟队列的场景1、CAS:---> compareAndSet(期望值,修改值)
比较并交换;
/** * CAS: ---> compareAndSet() * 比较并交换 */ public class CASDemo { public static void main(String[] args) { AtomicInteger atomicInteger = new AtomicInteger(5); System.out.println(atomicInteger.compareAndSet(5,2019)+" atomicInteger:"+atomicInteger.get()); System.out.println(atomicInteger.compareAndSet(5,1024)+" atomicInteger:"+atomicInteger.get()); } }
atomicInteger.getAndIncrement();为什么可以保证原子性?
因为底层使用的是Unsafe类:
CAS原理:
unsafe.getAndAddInt()
CAS原语:
CAS总结:
CAS的缺点:
1、循环时间长,开销大;
2、只能保证一个共享变量的原子操作;
3、引发出来的ABA问题?
1、循环时间长,开销大;
2、只能保证一个共享变量的原子操作;
当对一个共享变量执行操作时,我们可以使用循环CAS的方式来保证原子操作;
但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候可以用锁来保证原子性;
3、引发的ABA问题?
JUC下的原子引用封装类:AtomicReference<V>
@Getter @ToString @AllArgsConstructor class User{ String name; int age; } public class AtomicReferenceDemo { public static void main(String[] args) { User z3 = new User("z3",22); User l4 = new User("l4",25); AtomicReference<User> atomicReference = new AtomicReference<>(); atomicReference.set(z3); System.out.println(atomicReference.compareAndSet(z3,l4)+"\t"+atomicReference.get().toString()); System.out.println(atomicReference.compareAndSet(z3,l4)+"\t"+atomicReference.get().toString()); } }
解决ABA问题?AtomicStampedReference<V>();
原子引用+新增一种机制,例如版本号(类似于时间戳);
AtomicStampedReference<V>();
JUC下带有时间戳的原子引用类;
ABA问题产生的示例代码:
public class ABADemo {//ABA问题的解决 AtomicStampedReference<>(); static AtomicReference<Integer> atomicReference = new AtomicReference<>(100); public static void main(String[] args) { new Thread(() -> {//t1线程模拟ABA环境 atomicReference.compareAndSet(100, 101); atomicReference.compareAndSet(101, 100); }, "t1").start(); new Thread(() -> { //t2线程睡眠一秒,保证t1线程执行完ABA问题 try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(atomicReference.compareAndSet(100, 2019)+"\t"+atomicReference.get()); }, "t2").start(); } }
ABA问题的解决示例代码:
public class ABADemo {//ABA问题的解决 AtomicStampedReference<>(); 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问题的产生===="); new Thread(() -> {//t1线程模拟ABA环境 atomicReference.compareAndSet(100, 101); atomicReference.compareAndSet(101, 100); }, "t1").start(); new Thread(() -> { //t2线程睡眠一秒,保证t1线程执行完ABA问题 try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(atomicReference.compareAndSet(100, 2019)+"\t"+atomicReference.get()); }, "t2").start(); //睡眠2秒,保证t1、t2线程完成 try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("====以下是ABA问题的解决===="); new Thread(() ->{ int stamp = atomicStampedReference.getStamp(); System.out.println(Thread.currentThread().getName()+"\t 第一次的版本号:"+stamp); //t3睡眠一秒,保证t3、t4拿到同一个版本号 try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } atomicStampedReference.compareAndSet(100,101,atomicStampedReference.getStamp(),atomicStampedReference.getStamp() + 1); System.out.println(Thread.currentThread().getName()+"\t 第二次的版本号:"+atomicStampedReference.getStamp()); atomicStampedReference.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(); System.out.println(Thread.currentThread().getName()+"\t 第一次的版本号:"+stamp); //t4睡眠3秒,保证t3、t4拿到同一个版本号,并且保证t3执行完ABA try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } boolean result = atomicStampedReference.compareAndSet(100, 2019, stamp, stamp + 1); System.out.println(Thread.currentThread().getName()+"\t 是否修改成功:"+result +"\t当前实际版本号:"+atomicStampedReference.getStamp() +"\t当前实际最新值:"+atomicStampedReference.getReference()); },"t4").start(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?