CAS乐观锁失败重试的核心是线程主动感知冲突并安全重试:每次必须重新读取最新值,基于它重新计算目标值,再以最新值为预期值执行CAS;需防无限自旋、ABA问题,常用带限次/超时的while循环+AtomicStampedReference。

CAS 在乐观锁场景下处理失败重试,核心不是“强行成功”,而是让线程主动感知冲突、安全重试,不阻塞、不挂起、不破坏一致性。
失败时必须重新读取最新值再计算
不能沿用旧的预期值直接重试。因为 CAS 失败说明内存值已被其他线程修改,继续拿过期值比较必然再次失败,还可能引发逻辑错误。
- 每次重试前,都要从主内存(或 volatile 变量)重新读取当前实际值
- 基于这个最新值,重新执行业务逻辑(比如库存减1、计数加1),得出新的目标值
- 再用最新值作为预期值(A),新目标值作为待写入值(B),发起下一轮 CAS
典型自旋重试结构:while + compareAndSet
Java 中原子类(如 AtomicInteger、AtomicReference)封装了底层 Unsafe 的 CAS,常用模式是循环调用 compareAndSet 方法:
- 用 get() 获取当前值 → 计算 nextValue → 调用 compareAndSet(current, nextValue)
- 若返回 false,说明期间被抢占,立即回到开头重新读取
- 整个过程无锁、无 wait/notify、无线程调度开销
需要设置合理退出机制,避免无限自旋
在高竞争或长耗时场景中,纯自旋会浪费 CPU。生产环境应加入保护策略:
立即学习“Java免费学习笔记(深入)”;
- 限制最大重试次数(如 100 次),超限抛出 OptimisticLockingFailureException
- 结合时间阈值(如总耗时超过 50ms)主动放弃,转为退避或降级处理
- 对关键业务(如库存扣减),可配合数据库 version 字段 + AOP 统一拦截重试,实现跨 JVM 的乐观控制
注意 ABA 问题对重试逻辑的影响
单纯比对值相等,可能掩盖中间被修改又改回的“假一致”。例如 tail 指针从 A→B→A,CAS 会误认为未变而成功更新。
- 解决方法不是禁用重试,而是升级比较维度:用 AtomicStampedReference 增加版本号 stamp
- 每次 CAS 都要求“值 == 预期值 AND stamp == 预期 stamp”,stamp 自增确保每次修改唯一标识
- 重试时也要同步读取最新 stamp,否则新版 stamp 不匹配仍会失败


















