讲师中心 微信公众号
AI工具推荐 视频效率加速

详解Java并发中的AtomicMarkableReference_用于对象标记状态的原子原子更新

落静吖_5613

落静吖_5613

发布时间:2026-02-17 14:00:11

|

856人浏览过

|

来源于php中文网

原创

AtomicMarkableReference 是用于原子更新“带布尔标记的引用”的类,解决引用不变但逻辑状态(如删除、锁定)需同步变更的竞态问题;它通过内部版本戳防ABA,仅暴露boolean标记,适用于双态场景,使用时必须用get(boolean[])获取最新快照再CAS。

详解java并发中的atomicmarkablereference_用于对象标记状态的原子原子更新

AtomicMarkableReference 是什么,什么时候非用不可

它解决的是“带标记的引用”需要原子更新的场景,比如一个对象本身没变,但它的逻辑状态(如是否已删除、是否被锁定)变了,你既要读取对象,又要同时读取/更新这个标记,且整个操作不能被其他线程打断。普通 AtomicReference 只能保证引用更新原子,没法附带一个布尔标记;而用两个独立的原子变量(AtomicReference + AtomicBoolean)又无法保证二者更新的整体原子性——这就是 AtomicMarkableReference 存在的唯一理由。

  • 标记只能是 boolean,不是任意类型
  • 内部用“版本戳+标记”方式实现 ABA 防御,但不暴露版本号,只暴露标记
  • 适用于轻量级双态标记:例如缓存项是否已失效、节点是否已被逻辑删除、连接是否处于“正在关闭”状态

compareAndSet 怎么写才不会白忙活

compareAndSet 要求你提供「旧引用值」「旧标记值」「新引用值」「新标记值」四个参数,任何一项不匹配都会失败。常见错误是只关心引用是否相同,却忽略标记当前值。

  • 必须先调用 get 或 get(boolean[]) 拿到当前的引用和标记快照,再基于这个快照构造 compareAndSet 调用
  • 错误示范:ref.compareAndSet(oldObj, newObj, true, true) —— 这里 oldObj 可能早已被别的线程替换成 newObj,但标记已是 false,这次调用必然失败
  • 正确做法是用 boolean[] holder = new boolean[1] 接收标记,再传给 compareAndSet:
    boolean[] mark = new boolean[1];
    Node current = ref.get(mark);
    while (!ref.compareAndSet(current, current, mark[0], !mark[0])) {
      current = ref.get(mark);
    }
    

为什么 get(boolean[]) 比单独 get() 多一层必要

get() 只返回引用,丢掉了标记;get(boolean[]) 把标记写入你传入的数组第一个元素,这是唯一能一次性拿到引用+标记快照的方式。漏掉这一步,就等于在竞态条件下凭空猜标记值。

Java Api Extractor
Java Api Extractor

从 Java 项目中提取 Controller 层接口定义为 JSON 数据。

下载
  • 数组长度必须 ≥ 1,否则抛 NullPointerException
  • 数组只是个容器,不参与原子性保障,内容由方法内部写入
  • 如果你只需要标记不需要引用,仍得调用 get(new boolean[1]),别试图绕开

和 AtomicStampedReference 选哪个

两者都防 ABA,但设计目标不同:AtomicStampedReference 带整数版本号,适合需要多状态或递增版本的场景(如重试计数、乐观锁版本);AtomicMarkableReference 只带一个布尔标记,更轻量,语义更明确。

立即学习“Java免费学习笔记(深入)”;

  • 如果标记只有“是/否”两种含义,选 AtomicMarkableReference:代码更直白,内存占用略小(int vs boolean)
  • 如果将来可能扩展成“未开始/进行中/已失败/已重试2次”,立刻换 AtomicStampedReference
  • 别混用:拿 AtomicMarkableReference 的引用去塞进 AtomicStampedReference,编译过不了,运行也无意义

标记和引用是一体两面,拆开读就是埋雷;CAS 不是重试次数够多就能赢,而是每次重试都得基于最新快照——这点容易被忽略,尤其在嵌套条件判断里。

热门AI工具

更多
Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

相关专题

更多
java中boolean的用法
java中boolean的用法

在Java中,boolean是一种基本数据类型,它只有两个可能的值:true和false。boolean类型经常用于条件测试,比如进行比较或者检查某个条件是否满足。想了解更多java中boolean的相关内容,可以阅读本专题下面的文章。

2150

2023.11.13

java boolean类型
java boolean类型

本专题整合了java中boolean类型相关教程,阅读专题下面的文章了解更多详细内容。

163

2025.11.30

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

6839

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3285

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

4268

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

2905

2025.08.29

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4478

2023.08.10

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

40

2026.10.28

Vite 如何搭配 Vue.js
Vite 如何搭配 Vue.js

Vite搭配Vue.js专题汇集创建Vue 3项目、配置开发环境、路径别名、Vue插件、代理、多环境构建与调试的已审核文章,帮助读者完成从初始化到日常开发的配置。

20

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn