CAS和Atomic原子操作类详解
约 638 字大约 2 分钟
2025-10-09
CAS的核心是原子性(CAS 是一种无锁化的原子操作)。
CAS是指令(CPU硬件层面的),所以不存在线程上下文切换
CAS的流程
CAS是怎么实现原子性的?
通过Unsafe类提供的本地方法实现的,但Unsafe很多方法是由c++去实现的,最底层是调用CPU硬件的原子性指令 cmpxchg 去实现的(compare and exchange)。
CAS的实现原理?
原理是CAS里包含3个关键参数:
期望的旧值
将要更新的新值
要更新变量在对象内存中的偏移量地址
通过比较指定内存地址的当前值是否与期望的旧值是否相同,如果相同,则交换为新值,否则自旋重新执行。
原子操作正确场景:
- 读取内存位置 V 的当前值 A。
- 比较当前值 A 是否等于预期值 E。
- 如果相等,则交换为新值 U。
非原子操作的灾难场景:
- 线程1读取当前值
A。- 在线程1比较之前,线程2也读取了当前值
A。- 线程2将值从
A成功更新为B。- 线程1此时执行比较,发现当前值 仍然是
A(它读到的旧值),于是它也执行了更新操作。- 结果:线程2的更新被意外覆盖了!这完全违背了 CAS “只有在我之后没人修改过,我才能修改” 的设计初衷。
CAS存在ABA问题
库存原本是5,现在并发线程1要将其从5改为改为4(但是在准备修改为4时阻塞了),并发线程2要将其从5改为6,并发线程3将其从6改为5。等并发线程3执行完后,并发线程1介绍阻塞,将库存改为了4。
库存变化过程 5 --> 6 --> 5 --> 4
对业务没有影响(CAS的目的达到了,进行比对时,库存值确实没有变化。如果只关心结果是没问题的)
关心过程的案例,一个账户男女主同时在用,账户余额1万,男女主同时查询金额1万,女主取走1万消费,诈骗团伙转入1万,男主操作取款1万,ATM判断金额够,取款成功。
男主取款的1万是
解决方案,可以添加版本号,可使用AtomicStasmpedReference原子类。
