当前位置: 首页 > news >正文

Java并发利器:AtomicStampedReference解析

一、一句话理解

AtomicStampedReference是一个原子引用,它不仅维护一个对象引用,还附带一个整型“戳记(stamp)”,通过同时比较引用和戳记来实现更安全的 CAS(Compare-And-Swap)操作,从而避免经典的 ABA 问题。


二、什么是 ABA 问题?

场景举例:

假设有一个栈,初始状态为A → B → C,栈顶是 A。

  • 线程1 读取栈顶为 A,准备执行 CAS(期望 A,替换为 D)。
  • 此时线程2 弹出 A,再压入新节点 A’(内容相同但地址不同,或甚至同一个 A 被回收后重用)。
  • 栈变成:A → B → C(看起来没变)。
  • 线程1 执行 CAS:发现栈顶仍是 A,于是成功替换为 D。

但实际上,中间发生了变化(A 被弹出又压入),但 CAS 无法感知,这就是ABA 问题

💡 ABA 的本质:值看起来没变,但语义已变


三、AtomicStampedReference如何解决 ABA?

它给每个引用附加一个版本号(stamp)

  • 每次修改引用时,同时更新 stamp(比如 +1)。
  • CAS 操作必须同时匹配引用 + stamp
  • 即使引用值“看起来一样”,只要 stamp 不同,就认为是不同状态。

这样就能区分:

  • “真的是同一个状态” vs
  • “值碰巧相同,但中间被篡改过”

四、核心设计解析

1.内部类Pair<T>

privatestaticclassPair<T>{finalTreference;finalintstamp;// ...}
  • 引用 + stamp打包成一个不可变对象(final字段)。
  • 所有状态变更都通过原子地替换整个Pair对象实现。

✅ 这是一种典型的“不可变快照”设计。


2.volatile 引用

privatevolatilePair<V>pair;
  • 保证多线程对pair的读写具有可见性happens-before语义。
  • 但仅靠volatile无法保证原子性(比如 compare-and-set),所以需要 CAS。

3.关键方法:compareAndSet

publicbooleancompareAndSet(VexpectedReference,VnewReference,intexpectedStamp,intnewStamp){Pair<V>current=pair;returnexpectedReference==current.reference&&// 引用相等(注意:是 ==,不是 equals!)expectedStamp==current.stamp&&((newReference==current.reference&&newStamp==current.stamp)||casPair(current,Pair.of(newReference,newStamp)));}
注意点:
  • 引用比较用==:这是为了性能和语义一致性(通常用于指针/对象身份比较)。
  • 如果新值和当前值完全一样,直接返回true(避免不必要的 CAS)。
  • 否则,调用底层Unsafe.compareAndSwapObject原子替换pair

🔒 底层依赖sun.misc.Unsafe的 CAS 指令(硬件级原子操作)。


4.辅助方法

方法作用
getReference()/getStamp()分别获取当前引用和戳记
get(int[] stampHolder)一次性获取引用和戳记(避免两次读之间状态变化)
set(V, int)无条件设置新值(非原子组合操作,慎用)
attemptStamp(V, int)只更新 stamp,不改变引用(前提是引用仍等于期望值)

📌attemptStamp常用于“标记”场景,比如标记某个节点已被逻辑删除。


5.weakCompareAndSet的说明

publicbooleanweakCompareAndSet(...){returncompareAndSet(...);// 目前 JDK 中两者实现相同}
  • 注释提到它“可能虚假失败,且不提供内存顺序保证”。
  • 但在当前 HotSpot 实现中,它和compareAndSet行为一致。
  • 主要是为了未来在某些平台(如 ARM)上提供更弱但更快的 CAS 变体。

五、典型使用场景

1.无锁数据结构(Lock-Free Data Structures)

  • 如无锁栈、队列、链表等,需要检测 ABA 问题。
  • 示例:在实现ConcurrentLinkedQueue或自定义无锁栈时,用AtomicStampedReference包装头指针。

2.状态机带版本控制

  • 某个对象的状态变更需要记录“版本”,防止旧状态覆盖新状态。

3.资源回收标记

  • 先用attemptStamp将 stamp 设为“已删除”(如 -1),再安全回收。

六、使用示例

AtomicStampedReference<String>ref=newAtomicStampedReference<>("A",0);int[]holder=newint[1];Stringcurrent=ref.get(holder);intcurrentStamp=holder[0];// 尝试将 "A" (stamp=0) 替换为 "B" (stamp=1)booleansuccess=ref.compareAndSet("A","B",0,1);if(success){System.out.println("Update succeeded");}

⚠️ 注意:expectedReference必须是同一个对象引用==成立),不能只是equals相等。


七、与AtomicReference对比

特性AtomicReference<V>AtomicStampedReference<V>
存储内容仅引用引用 + int stamp
解决 ABA❌ 否✅ 是
内存开销稍大(多一个 int + Pair 对象)
使用复杂度简单稍高(需管理 stamp)
性能更快略慢(多一次 int 比较)

八、注意事项

  1. 引用比较是==,不是equals
    → 适用于对象身份比较,不适合值语义(除非你确保同一对象复用)。

  2. stamp 需要手动管理
    → 通常每次修改时stamp + 1,或用时间戳、逻辑版本号。

  3. 不要滥用
    → 如果你的场景不可能出现 ABA(比如引用永远不会被回收重用),用AtomicReference更高效。

  4. Java 9+ 替代方案?
    → 虽然有VarHandle,但AtomicStampedReference仍是解决 ABA 的标准工具。


九、总结

AtomicStampedReference是 Java 并发编程中解决 ABA 问题的经典工具。它通过“引用 + 版本戳”的组合,使得 CAS 操作能够感知到中间状态的变化,从而保证无锁算法的正确性。

它不是日常开发常用类,但在实现高性能、无锁并发数据结构时,它是不可或缺的“利器”。

如果你正在编写 lock-free 或 wait-free 算法,或者遇到因对象复用导致的并发 bug,AtomicStampedReference很可能就是你需要的答案。

http://www.cnnetsun.cn/news/185716.html

相关文章:

  • Jasminum插件生态整合:构建智能科研文献管理平台
  • Vue3 Element Admin:企业级后台管理系统的技术革新与实战指南
  • Zotero文献去重插件完整指南:智能合并重复条目
  • 2025必存!小白秒变创作大神!0成本解锁AI写歌自由,4款顶级免费工具
  • 3分钟学会Zotero自动下载PDF:SciPDF插件完整教程
  • BabelDOC实战指南:智能PDF翻译工具的高效应用技巧
  • 嘉立创PCB布线项目应用:电源模块在EasyEDA中的布局布线
  • 如何轻松解决微信网页版访问限制?wechat-need-web插件全解析
  • 超详细版CubeMX安装与串口下载驱动配置流程
  • 小红书下载器终极指南:3分钟掌握免费无水印下载技巧
  • 如何在macOS上完美运行ComfyUI-Manager?终极兼容性实战指南
  • XHS-Downloader终极指南:轻松下载小红书无水印内容
  • SketchUp STL插件:从3D设计到实体打印的5个高效秘诀
  • ComfyUI模型路径配置终极指南:3步解决工作流验证失败问题
  • HarmonyOS应用开发—页面路由
  • 大文件上传:秒传、断点续传、分片上传
  • WindowsCleaner:一键解决C盘爆红的智能清理神器
  • 小红书无水印下载器完整教程:从零开始快速掌握
  • 深蓝词库转换:彻底告别输入法切换困扰的终极解决方案
  • vivado2018.3安装步骤从零实现:适合入门者的实践指导
  • 原神帧率解锁:如何突破60帧限制,释放显示器真正潜力
  • 快速解决C盘爆满:WindowsCleaner终极使用教程
  • Packet Tracer使用教程:手把手教你保存与导出项目
  • Windows系统优化实战:三步彻底解决C盘爆满问题
  • 全网围观的2025大语言模型回顾:AI大牛karpathy总结了六大关键节点
  • c# Visual Studio基础语法-循环
  • ViGEmBus虚拟游戏控制器驱动:完整部署与配置指南
  • 深蓝词库转换:跨平台输入法词库同步的完整解决方案
  • 微信网页版无法访问?3分钟解决你的所有烦恼!
  • 深蓝词库转换:跨平台词库互通终极方案