如何避免ABA问题中变量值循环变更引发的版本控制风险?
- 内容介绍
- 相关推荐
本文共计946个文字,预计阅读时间需要4分钟。
ABA+问题并非是值‘没变’,而是值‘变过又回来’但未被察觉——它让CAS操作在逻辑上误判状态未变,从而绕过本应截断的并发修改。
ABA 问题是怎么发生的
一个共享变量初始为 A,线程1读取后准备用 CAS 把它从 A 改成 C,但还没执行就被挂起;此时线程2介入,先把它改成 B,再改回 A;线程1恢复时发现值仍是 A,就直接完成 CAS,把 A 改成了 C。
表面看一切正常,但变量实际经历了 A→B→A 的完整变迁。如果 B 阶段代表资源已被释放、节点已被复用或余额已被扣减,那线程1的操作就可能破坏数据结构或业务语义。
- 链表删除时,旧节点 A 被删,新节点 A(同值不同对象)被压入,线程1误删了新节点
- 无锁队列中,head 指针地址看似没变,但所指对象已被回收重用,导致野指针访问
- 金融转账中,账户余额从 100→0→100,CAS 认为“没动过”,跳过余额校验直接扣款
为什么单纯比对值会失效
CAS 的原子指令只检查内存地址当前值是否等于预期值,不记录历史、不感知生命周期、不绑定上下文。它本质上是“快照式比对”,而非“过程式验证”。只要最终值匹配,就放行更新,完全忽略中间是否发生过状态跃迁。
这就像用门禁卡开门:系统只认卡号,不管这张卡是否刚被复制、挂失、再补办——只要卡号对,门就开。
本文共计946个文字,预计阅读时间需要4分钟。
ABA+问题并非是值‘没变’,而是值‘变过又回来’但未被察觉——它让CAS操作在逻辑上误判状态未变,从而绕过本应截断的并发修改。
ABA 问题是怎么发生的
一个共享变量初始为 A,线程1读取后准备用 CAS 把它从 A 改成 C,但还没执行就被挂起;此时线程2介入,先把它改成 B,再改回 A;线程1恢复时发现值仍是 A,就直接完成 CAS,把 A 改成了 C。
表面看一切正常,但变量实际经历了 A→B→A 的完整变迁。如果 B 阶段代表资源已被释放、节点已被复用或余额已被扣减,那线程1的操作就可能破坏数据结构或业务语义。
- 链表删除时,旧节点 A 被删,新节点 A(同值不同对象)被压入,线程1误删了新节点
- 无锁队列中,head 指针地址看似没变,但所指对象已被回收重用,导致野指针访问
- 金融转账中,账户余额从 100→0→100,CAS 认为“没动过”,跳过余额校验直接扣款
为什么单纯比对值会失效
CAS 的原子指令只检查内存地址当前值是否等于预期值,不记录历史、不感知生命周期、不绑定上下文。它本质上是“快照式比对”,而非“过程式验证”。只要最终值匹配,就放行更新,完全忽略中间是否发生过状态跃迁。
这就像用门禁卡开门:系统只认卡号,不管这张卡是否刚被复制、挂失、再补办——只要卡号对,门就开。

