CAS自旋锁
手写自旋锁
public class SpinLockDemo { AtomicReference<Thread> atomicReference = new AtomicReference<>(); public void lock(){ Thread thread = Thread.currentThread(); System.out.println(thread.getName()+ " --- come in"); //while循环持续尝试拿锁,成功了才能跳出循环 while (!atomicReference.compareAndSet(null, thread)){ } } public void unlock(){ Thread thread = Thread.currentThread(); atomicReference.compareAndSet(thread,null); System.out.println(thread.getName()+ " --- task over, unlock"); } }
CAS的两大缺点
1,循环时间长,性能开销很大。
2,会导致"ABA"问题:CAS算法的一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并替换,那么在这个时间差类会导致数据的变化
比如说一个线程1从内存位置V中取出A,这时候另一个线程2也从内存中取出A,并且线程2进行了一些数值操作变成了B,然后线程2又将V位置的数据变成A,这时候线程1进行CAS操作发现内存中仍然是A,预期OK,然后线程1操作成功。
尽管线程1的CAS操作成功,但是不代表这个过程就是没有问题的。
如何避免ABA问题?
使用AtomicStampedReference,也就是带有版本号的AtomicReference
//构造器:Book (类名) javabook (实例对象) 1 (版本号) AtomicStampedReference<Book> stampedReference = new AtomicStampedReference<>(javaBook, 1) //CAS方法:括号内依次为(预期对象,新对象,预期版本号,新版本号) boolean flag = stampedReference.compareAndSet(javaBook, mysqlBook, stampedReference.getStamp(), stampedReference.getStamp()+1)
标签:
JUC
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律