java并发中正确类名为atomicstampedreference,用于解决cas的aba问题:通过“引用+版本号”原子对校验,避免对象复用导致的状态误判;必须用get(int[])原子读取,版本号需显式管理并每次重读。

Java 并发编程中没有 AtomicStampableReference 这个类,正确名称是 AtomicStampedReference。名字里是 “Stamped”(盖戳),不是 “Stampable”(可盖戳的)——这是常见拼写错误,会导致编译失败或找不到类。
为什么需要 AtomicStampedReference
它解决的是 CAS 操作中的 ABA 问题:一个引用值从 A 变成 B,又变回 A,单纯比对引用会误判“没变”,但背后对象可能已被释放、复用或状态断裂。比如无锁栈弹出节点后又被压回,表面引用相同,实际内存已重用。
AtomicStampedReference 不消除 ABA,而是通过“引用 + 整数版本号”绑定成原子对,让每次 CAS 同时校验两者。只要中间发生过修改(哪怕最后值相同),版本号就不同,CAS 就失败,从而暴露问题。
必须用 get(int[]) 原子读取值和版本号
不能分开调用 getReference() 和 getStamp() —— 两次调用之间可能被其他线程修改,导致拿到的值和 stamp 来自不同快照,CAS 必然误判。
- 正确写法:int[] stamp = new int[1]; String cur = ref.get(stamp); int s = stamp[0];
- 错误写法:String cur = ref.getReference(); int s = ref.getStamp(); // 非原子,不安全
这个 int[] 是唯一受保护的入口,JDK 故意不提供更便捷方式,就是为了强制你遵守原子性约束。
版本号必须由你显式管理,且每次都要重读
stamp 不自动递增,也不自带业务语义。硬编码 newStamp(如写死为 s + 1 却不重读当前 stamp)会导致 CAS 总是失败或漏检 ABA。
- 每次 compareAndSet 前,必须基于刚 get() 到的 stamp 计算 newStamp,例如:ref.compareAndSet(oldVal, newVal, s, s + 1)
- 在循环重试逻辑中,每轮都得重新调用 ref.get(stamp),不能缓存 stamp[0] 多次使用
- 若状态跃迁固定(如 INIT → PROCESSING → DONE),可用语义化整数(0/1/2)代替自增,更清晰且避免溢出风险
适用场景与边界要清楚
它专治“物理地址复用”类 ABA:对象池节点回收再分配、无锁链表指针变更、缓存 key 被清理后重用等。
- 适合:节点复用、栈/队列头指针更新、带生命周期的对象引用
- 不适合:开关反复切换(A ↔ A 是合法行为)、多字段强一致性更新(它只保单引用+stamp 原子性,不替代事务或状态机)
- 注意:Android API 24 以下不支持 get(int[]);实测性能比 AtomicReference 低 5%–15%;int stamp 溢出虽罕见,但超长生命周期系统需评估 wrap-around 风险
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











