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

如何解决 CAS 的 ABA 问题:从版本号机制到 AtomicStampedReference 深度解析

文章目录问题一、 什么是 ABA 问题二、 为什么不能通过“加锁”来解决三、 核心方案引入版本号四、 推荐实现AtomicStampedReference1. 内部类 Pair2. CAS 对象引用五、 实战演示拦截 ABA 过程六、 延伸AtomicMarkableReference总结问题在多线程高并发场景下CAS (Compare And Swap比较并交换)是实现无锁化编程的核心基石。它利用 CPU 的原子指令如cmpxchg实现了极高性能的并发更新。然而CAS 并非完美其中最经典的挑战便是ABA 问题。本篇博客将深入探讨 ABA 问题的本质、为何不能使用“加锁”来解决以及 Java 如何通过AtomicStampedReference优雅地化解这一难题。一、 什么是 ABA 问题CAS 的逻辑是“我认为值应该是 A如果是则更新为 B。”ABA 现象描述线程 T1 读取共享变量值为A。线程 T2 介入将值从A 改为 B随后又将其从B 改回 A。线程 T1 恢复执行进行 CAS 操作。它发现值依然是A于是判定“没有变化”更新成功。潜在风险虽然数值上看起来没变但变量的状态或引用指向的内容可能已经发生了本质变化。在某些数据结构如无锁栈或链表中这可能导致指针悬挂或逻辑混乱。二、 为什么不能通过“加锁”来解决面对并发冲突最简单的直觉是加锁synchronized或ReentrantLock。但在 CAS 场景下这与无锁的初衷背道而驰违背设计初衷CAS 存在的意义就是为了无锁化避免内核态切换、上下文切换和线程阻塞带来的巨大开销。性能瓶颈加锁会将并发操作变为串行在高竞争环境下锁的开销远大于 CAS 自旋。复杂度增加锁可能引入死锁、活锁等风险。结论解决 CAS 的问题必须坚持使用乐观锁的思想在“无锁”的框架内寻找方案。三、 核心方案引入版本号解决 ABA 的标准思想是“不仅比较值还要比较版本号。”我们为变量额外维护一个单调递增的版本号或时间戳。判定逻辑(当前值 预期值) (当前版本号 预期版本号)。即使值从 A 变回了 A版本号也会从 1 变为 3CAS 依然会检测到变化并拦截。四、 推荐实现AtomicStampedReference在 Java 中我们不需要手动通过AtomicReferenceAtomicInteger来维护这种关系。因为手动维护无法保证“值版本号”两者同时更新的原子性Java 并发包提供了AtomicStampedReferenceV其底层设计极其精妙1. 内部类 Pair它将实际引用reference和版本戳stamp封装在一个静态内部类Pair中2. CAS 对象引用AtomicStampedReference内部维护一个volatile PairV pair对象。它的 CAS 操作实际上是对Pair对象引用的整体替换。由于替换一个对象的引用是原子指令从而实现了“值版本号”的联合原子更新。五、 实战演示拦截 ABA 过程以下代码演示了如何利用AtomicStampedReference识别并拦截 ABA 问题importjava.util.concurrent.atomic.AtomicStampedReference;/** * 演示使用 AtomicStampedReference 解决 CAS 的 ABA 问题 */publicclassABASolution{publicstaticvoidmain(String[]args){// 初始化值为A初始版本号为1AtomicStampedReferenceStringasrnewAtomicStampedReference(A,1);// --- 线程2模拟 ABA 操作 ---newThread(()-{intstampasr.getStamp();// 获取初始版本号: 1System.out.println(线程2读取初始版本号 stamp);// 第一次修改A - B版本号 1 - 2asr.compareAndSet(A,B,stamp,stamp1);// 第二次修改B - A版本号 2 - 3asr.compareAndSet(B,A,asr.getStamp(),asr.getStamp()1);System.out.println(线程2完成 ABA 篡改当前版本号为 asr.getStamp());}).start();// --- 线程1受害线程尝试更新 ---try{// 确保线程2先完成 ABA 操作Thread.sleep(500);}catch(InterruptedExceptione){e.printStackTrace();}intexpectedStamp1;// 线程1 认为版本号还是 1StringexpectedValA;// 尝试 CAS预期值 A预期版本 1 - 更新为 C版本 2booleansuccessasr.compareAndSet(expectedVal,C,expectedStamp,expectedStamp1);System.out.println(线程1 CAS 操作结果success);System.out.println(当前实际值asr.getReference()当前实际版本号asr.getStamp());}}运行结果分析虽然当前值确实是 “A”但由于版本号已经从1 变为了 3线程 1 的 CAS 操作会返回false。ABA 问题被完美解决。六、 延伸AtomicMarkableReference如果不关心变量被修改了几次只关心它是否被修改过可以使用更轻量级的AtomicMarkableReference。它内部维护的是一个boolean类型的标记位逻辑与AtomicStampedReference一致但开销略小。总结ABA 问题是 CAS 在检测变量状态时的逻辑漏洞。拒绝加锁应通过引入版本号Stamp维持乐观锁的性能优势。推荐工具直接使用AtomicStampedReference它通过内部封装Pair对象利用硬件级 CAS 保证了值与版本号更新的原子性。

相关文章:

如何解决 CAS 的 ABA 问题:从版本号机制到 AtomicStampedReference 深度解析

文章目录问题一、 什么是 ABA 问题?二、 为什么不能通过“加锁”来解决?三、 核心方案:引入版本号四、 推荐实现:AtomicStampedReference1. 内部类 Pair2. CAS 对象引用五、 实战演示:拦截 ABA 过程六、 延伸&#xff…...

...........

.................

Linux基础操作——学习记录

Linux的文件结构是多叉树,叶子节点是普通文件或空目录,非叶子节一定是一个非空目录基础操作clear:清屏AITENTER:全屏/退出全屏adduser 用户名: 创建新用户passwd 用户名 : 重置密码userdel -r 用户名&#…...

AI 时代的程序员生存指南:我是如何用 AI 提升 10 倍开发效率的

AI 时代的程序员生存指南:我是如何用 AI 提升 10 倍开发效率的从"抗拒 AI"到"离不开 AI",我的思维转变和实操经验全部分享引言:一个程序员的焦虑去年这个时候,程序员都特别焦虑。因为那段时间,AI …...

vim使用verible插件进行verilog语法检查

github上下载verible后,可在不联网的情况下,在vim中检查verilog语法,或者格式优化(自动缩进等),verible下还有其他插件,待探索(xxx --helpfull)...

2025_NIPS_Praxis-VLM: Vision-Grounded Decision Making via Text-Driven Reinforcement Learning

一、主要内容总结 1. 研究背景与问题 现有视觉语言模型(VLMs)在多模态任务中表现出色,但缺乏复杂场景下的情境推理能力,难以支撑机器人、交互式助手等领域的决策需求。传统增强VLMs推理能力的方法依赖大规模图文配对数据,这类数据标注成本高、获取难度大,尤其在多样化现…...

OpenClaw 超级 AI 实战专栏【模型推理与实战】(五)推理参数调优:精度、速度、显存平衡

目录 一、核心认知:OpenClaw 推理的 “三角平衡” 逻辑 二、OpenClaw 核心推理参数详解(按优先级排序) 三、分场景调优策略(附 OpenClaw 实战代码) 场景 1:低配显卡(4G/6G 显存,如 GTX 1050/1650) 场景 2:中高配显卡(8G/12G/16G 显存,如 RTX 3060/3090/A100)…...

2025_NIPS_IR-OptSet: An Optimization-Sensitive Dataset for Advancing LLM-Based IR Optimizer

文章核心总结与创新点 主要内容 本文针对传统编译器依赖手工优化规则、扩展性差的问题,提出首个公开的优化敏感数据集IR-OptSet,用于提升基于大语言模型(LLMs)的中间表示(IR)优化器性能。该数据集包含170K条LLVM IR样本,源自8个优化领域的1704个开源仓库,定义了代码分…...

Java对象头:深入理解对象存储的核心机制

Java对象结构 实例化一个Java对象之后,该对象在内存中的结构是怎么样的?Java对象(Object实例)结构包括三部分:对象头、对象体和对齐字节,具体下图所示Java对象的三部分 对象头 对象头包括三个字段&#xff…...

Swift构造过程介绍

Swift 构造过程概述Swift 的构造过程是实例化类、结构体或枚举时的重要机制。构造过程通过构造器(init)实现,确保实例在首次使用前完成正确的初始化。Swift 的构造器无需返回值,其主要任务是初始化存储属性。默认构造器如果结构体…...

Pytorch之torch.nn.Conv2d详解

卷积层是卷积神经网络(CNN)的核心组件,而torch.nn.Conv2d作为 PyTorch 中实现二维卷积的核心类,广泛应用于图像分类、目标检测、语义分割等计算机视觉任务。本文将从基础概念、参数详解、使用示例到核心原理,全方位拆解…...

ROS2 -03-工作空间与功能包

文章目录ROS2 工作空间与功能包完全指南一、ROS2 工作空间(Workspace)1. 什么是工作空间?2. 工作空间的目录结构3. 工作空间的类型:Overlay 与 Underlay4. 创建工作空间5. 编译工作空间二、ROS2 功能包(Package&#x…...

MTP管理培训

MTP管理培训 这个是纯管理课程,技术管理还有不同 该套课程以“理”为核心,从“可实操性”入手,阐述了不因人是否天生具有管理特质,也能做好管理。 MTP(Management Training Program/Plan),原义为…...

OBS怎么调美颜?OBS怎么打开美颜功能?

OBS Studio 实现美颜主要有内置滤镜、第三方插件、摄像头硬件美颜三种方式,今天主要介绍第三方插件的用法: 一、基础准备 确保已安装 OBS Studio 最新版(推荐 29.1.3 及以上,稳定性更佳)。 摄像头已连接并正常识别&a…...

计算机毕业设计springboot中药材仓储管理系统的分析与实现 基于SpringBoot框架的中药饮片智能库存与质量追溯平台 中医药材冷链物流与数字化仓储运营管理系统

计算机毕业设计springboot中药材仓储管理系统的分析与实现0j9h07d8(配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。随着中医药的全球化推广和国内市场需求的增长,中药…...

LeetCode 11:盛最多水的容器(C语言实现)

题目描述给定一个长度为 n 的整数数组 height。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i])。请你找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。注意: 你不能倾斜容器。示…...

Unreal Engine5 笔记(持续更新)

C Debug及UE_Log debugPrint GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, "Begin play"); 含参print int a 100; GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, FString::Printf(TEXT("%d"), a));绘制调制函数 #include &qu…...

基于航空影像的道路异常状态识别 无人机道路阻断巡检 道路减速带识别 无人机道路施工巡检 无人机斑马线监测 道路场景计算机视觉数据集Yolo第10552期

道路场景计算机视觉数据集 README数据集核心信息概览(多数为背景)项目内容类别数量4类类别中文名称阻断道路、减速带、施工中、斑马线图像数量800数据集格式YOLO格式核心应用价值基于航空影像的道路异常状态实例分割,支撑智能交通管理与道路运维决策 往期热门主题 主…...

计算机毕业设计springboot社区便民服务平台 基于SpringBoot框架的智慧社区综合服务运营平台 城市社区数字化生活与多元服务集成管理系统

计算机毕业设计springboot社区便民服务平台9pqty086(配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。在快速城市化的进程中,社区作为城市的基本单元,其服务…...

基于STC8H8K64U的光学仪器协同采集平台设计

1. 项目概述本项目面向高校及科研院所实验室场景,构建一套基于STC8H8K64U单片机的多光学仪器协同控制与远程数据采集平台。其核心目标并非替代专用仪器控制器,而是作为轻量级、可扩展的“仪器粘合层”,解决实验室中多品牌、多协议光学设备&am…...

ROS2功能包构建与文件结构解析:从colcon编译到项目部署

1. 从零开始:理解ROS2功能包与工作空间 如果你刚开始接触ROS2,可能会被一堆新名词搞得有点懵:功能包、工作空间、colcon、ament……别担心,这很正常。我刚开始用ROS2的时候,也花了不少时间才把这些概念理清楚。今天&am…...

Nacos 3.0新特性解析:为什么控制台端口独立为8080?

Nacos 3.0架构演进:控制台端口独立背后的深度安全与运维考量 如果你是一位长期使用Nacos的开发者,从1.x版本一路升级过来,可能会对端口号的变化感到一丝困惑。最初,访问http://localhost:8848/nacos就能搞定一切;到了2…...

新媒体内容创作:使用DeOldify为历史题材短视频生成彩色素材

新媒体内容创作:使用DeOldify为历史题材短视频生成彩色素材 最近刷短视频,是不是经常看到一些老电影片段、历史纪录片被“上色”了?黑白画面一下子变得色彩鲜活,人物和场景都生动了起来,点赞和评论量往往也特别高。作…...

WuliArt Qwen-Image Turbo避坑指南:解决黑图、显存不足等常见问题

WuliArt Qwen-Image Turbo避坑指南:解决黑图、显存不足等常见问题 1. 为什么你的第一张图总是“黑屏”或“爆显存”? 你满怀期待地部署好WuliArt Qwen-Image Turbo,输入精心构思的Prompt,点击生成,然后……屏幕右侧一…...

C语言文件操作实战:读写二进制图片数据调用DeOldify服务

C语言文件操作实战:读写二进制图片数据调用DeOldify服务 你是不是也好奇,那些老照片上色服务背后是怎么运作的?作为一个C/C开发者,可能更想知道,如何用我们最熟悉的语言,从底层去实现图片的读取、发送和保…...

AI论文投稿指南:如何选择最适合你的CCF-A/B/C类期刊(附审稿周期对比)

AI论文投稿实战指南:从期刊选择到录用提速的深度策略 每次打开投稿系统,看着长长的期刊列表,你是不是也感到一丝迷茫?投顶刊怕周期太长耽误毕业,投普通期刊又担心影响力不够。在人工智能这个快速迭代的领域&#xff0c…...

ESP32开发新篇——VSCode插件助力ESP-IDF环境一键配置与实战

1. 为什么你需要VSCode插件开发ESP32? 第一次接触ESP32开发的朋友,往往会被官方推荐的ESP-IDF开发环境吓到。传统的安装方式需要手动配置Python、Git、CMake、Ninja等一堆工具链,光是环境变量配置就能劝退不少新手。我至今记得三年前第一次搭…...

Phi-4-reasoning-vision-15B企业级部署:supervisor托管+健康检查全链路

Phi-4-reasoning-vision-15B企业级部署:supervisor托管健康检查全链路 1. 引言:为什么需要企业级部署? 想象一下这个场景:你费了九牛二虎之力,终于把最新的视觉大模型部署到了服务器上。它运行得不错,能看…...

PaddleOCR v4实战:如何用SVTRNet微调训练提升中文标点符号识别准确率?

PaddleOCR v4实战:如何用SVTRNet微调训练提升中文标点符号识别准确率? 在实际处理海量中文文档时,无论是教育机构的历年档案、政府部门的公文流转,还是出版行业的古籍数字化,我们总会遇到一个看似微小却影响深远的难题…...

Dify 2026插件生态已剧变,你还在用v1.2旧范式?3类即将失效的API调用方式及2026兼容迁移路径

第一章:Dify 2026插件生态演进全景图Dify 2026标志着插件架构从松散集成迈向深度协同的质变节点。其核心突破在于引入「双向契约式插件协议」(BCP),使插件与平台在启动、上下文注入、状态同步及卸载全生命周期中具备可验证的行为契…...