AtomicMarkableReference 是 Java 中用于原子更新引用及其布尔标记的工具类,通过 compareAndSet 同时校验引用和 mark 值实现双状态原子操作,适用于逻辑删除等二元状态场景。

AtomicMarkableReference 是 Java 并发包(java.util.concurrent.atomic)中用于实现带“标记位”的原子引用的工具类。它允许你**同时对一个引用及其关联的布尔标记(mark)进行原子更新**,常用于解决 ABA 问题的变种场景,比如需要区分“逻辑上相同但状态不同”的引用变化(如节点被回收又复用、连接被关闭又重连等)。
核心作用:绑定引用与标记,一次 CAS 解决双状态更新
普通 AtomicReference 只能保证引用本身的原子性;而 AtomicMarkableReference 把引用和一个布尔值(mark)打包成一个不可分割的单元。它的 compareAndSet 方法要求**引用值和 mark 值都匹配才能成功更新为新引用 + 新 mark**,避免了单独维护 mark 导致的竞态。
典型使用模式:
- mark = false 表示“正常/可用/未标记”
- mark = true 表示“已标记/失效/待清理/已删除”
基本用法:创建、读取、原子更新
构造时需传入初始引用和初始标记值:
立即学习“Java免费学习笔记(深入)”;
AtomicMarkableReference<String> ref = new AtomicMarkableReference<>("hello", false);
获取当前值和标记需**一起读取**(避免中间被修改):
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
String currentRef; boolean currentMark; // get() 返回的是内部封装的对象,需用以下方式安全读取 currentRef = ref.getReference(); currentMark = ref.isMarked(); // 或 ref.get(new boolean[1]),返回引用,mark 写入数组
原子更新(CAS)是关键操作:
// 尝试将当前引用 "hello" 且 mark == false 的状态,更新为 "world" 和 true
boolean success = ref.compareAndSet("hello", "world", false, true);
// 只有当前引用是 "hello" 且 mark 是 false 时才成功
典型应用场景:无锁栈/队列中的节点标记删除
在并发数据结构中,删除节点时不能直接置 null(可能正被其他线程遍历),而是先打个标记(mark = true),后续再真正回收。这样可避免 ABA 问题中“节点被弹出 → 回收 → 复用 → 再入栈”导致的逻辑错误。
例如,在无锁栈的 pop 操作中:
- 读取栈顶节点及 mark 状态
- 若 mark == true,说明该节点已被逻辑删除,应跳过并重试
- 若 mark == false,尝试用 CAS 将其 mark 设为 true(逻辑删除)
- 成功后,再用另一个 CAS 将栈顶指针指向下一个节点
注意点:标记位只有 true/false,别试图编码多状态
mark 是单个布尔值,仅适合二元状态建模(如有效/无效、启用/禁用、未处理/已处理)。如果需要多个状态(如“初始化/运行中/暂停/终止”),应改用 AtomicStampedReference(带整数 stamp)或更高级的并发控制机制(如 StampedLock、状态机 + volatile 字段)。
另外,get(boolean[] markHolder) 方法会把当前 mark 写入传入的数组(长度至少为 1),这是为了**一次性读取引用和 mark**,避免两次读取之间发生变更 —— 这是线程安全的关键细节。

















