atomicstampedreference反序列化后stamp重置为0、仅reference保留原值,因stamp字段被声明为transient;需手动保存stamp并重建实例,或改用versionedref等pojo解耦序列化与原子操作。

Java 中 AtomicStampedReference 在序列化与反序列化后,reference 和 stamp 的状态**不会自动恢复为原始值**,而是会丢失 stamp 信息,仅保留 reference 的反序列化结果,stamp 被重置为默认值(0)。
序列化机制不支持 stamp 的持久化
AtomicStampedReference 实现了 Serializable 接口,但其内部 stamp 字段被声明为 transient(见 JDK 源码),意味着它不会参与默认序列化过程。只有 reference 字段会被序列化(前提是 reference 本身可序列化);而 stamp 在反序列化时由构造函数初始化为 0。
- 反序列化后得到的实例中:
getReference()返回原 reference 的反序列化对象(若 reference 可序列化) -
getStamp()总是返回0,无论原 stamp 是多少 - 这导致 ABA 问题防护能力在反序列化后完全失效
手动保存 stamp 需额外处理
若业务逻辑依赖 stamp 值(例如版本号、时间戳、状态计数器),必须在序列化前显式提取并单独保存 stamp,反序列化后再用该值重建 AtomicStampedReference 实例。
- 序列化时:调用
getStamp()获取当前 stamp,与 reference 一起写入输出流或 JSON 等结构 - 反序列化时:先还原 reference,再用保存的 stamp 构造新实例:
new AtomicStampedReference(ref, savedStamp) - 注意:不能直接反序列化原有对象后修改 stamp(因为 stamp 是私有 final 字段,无 public setter)
替代方案:避免序列化 AtomicStampedReference 实例
更稳妥的做法是不在网络传输或持久化场景中直接序列化 AtomicStampedReference 对象,而是将业务语义层面的“引用+版本”拆解为普通字段管理。
- 例如定义一个 POJO:
class VersionedRef<t> implements Serializable { T ref; int version; }</t> - 需要原子更新时,再包装成
AtomicStampedReference(仅在内存中使用) - 这样既保证序列化安全,又保留对 stamp 的完全控制权
测试验证 stamp 重置行为
可通过简单测试确认该行为:
AtomicStampedReference
byte[] bytes = serialize(asr); // 自定义序列化方法
AtomicStampedReference
System.out.println(restored.getReference()); // "hello"
System.out.println(restored.getStamp()); // 0,不是 123
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











