JJava 知识库
JAVA INTERVIEW

高频面试题

Java多线程进阶约 2 分钟

用 CAS 做库存或状态更新时,值改回原值会有什么风险?项目里怎么避免 ABA?

参考回答约 2 分钟 · 口语表达
我的判断

ABA 的风险是值看起来回到原样,但中间发生过业务变化;库存和订单状态通常用版本号或单调状态规则解决。

比如订单状态从 INIT 变成 CANCELLED,又因补偿被写回 INIT。另一个线程只比较当前值,会以为从未变化,继续执行一段基于旧前提的逻辑。内存结构可以用 AtomicStampedReference,把值和版本一起 CAS。

数据库里更常见的是乐观锁:

UPDATE orders
SET status = ?, version = version + 1
WHERE id = ? AND version = ?;

状态机如果本身只能单向流转,也会把合法前置状态写进 WHERE,拒绝倒退。消息消费再用事件 ID 或业务请求号幂等,不能只依赖状态值。

简单库存数字从 10 变 9 再回 10 是否有风险,要看业务是否关心中间过程;不关心就没必要为了术语增加版本。先找被破坏的不变量,再决定是否需要防 ABA。