一文详解CAS
CAS 详解 场景示例CASCompare And Swap比较并交换是无锁乐观锁的原子操作CPU 硬件指令支持不是 Java 独有的概念Java 里Unsafe类提供 CAS 底层方法AtomicInteger等原子类就是基于 CAS 实现。一、核心原理CAS 包含 3 个参数V(内存地址上的实际值)A(预期旧值)B(要更新的新值)逻辑比较判断内存当前值V是否 预期旧值A如果相等 → 说明期间没有被别人修改把 V 更新成 B返回 true如果不相等 → 说明已经被其他线程改过更新失败返回 false不做修改一句话我认为现在的值是 A如果确实还是 A我就改成 B变了就放弃修改重试。⚠️ 重点CAS 是原子指令一条 CPU 指令完成比较 交换不会出现比较和赋值中间被线程切换打断的问题.所以不需要 synchronized 重量级锁属于乐观锁假设并发冲突概率不高不加锁冲突了重试。二、Java 中 CAS 底层入口sun.misc.Unsafe的 native 方法// var1对象var2字段偏移量var4预期值var5新值 public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);AtomicInteger.getAndIncrement()自增底层就是// 伪代码 do { A get(); // 拿到当前预期旧值A B A 1; // 新值B } while( ! compareAndSwapInt(this, offset, A, B) ); // CAS失败就循环重试三、CAS 的 3 大经典问题面试高频1. ABA 问题现象线程 1 读取值 A线程 2 把 A 改成 B再改回 A线程 1 执行 CAS 时发现还是 A认为没被修改成功更新但中间发生过修改。举例子初始值V AT1读取 VA准备 CAS此时时间片被抢走暂停T2把 V 从 A→B再把 V 从 B→AT1 恢复发现 VACAS 成功。T1 感知不到中间发生过变化解决方案版本号时间戳每次修改带上版本号比较的时候同时比较【值 版本】。AtomicStampedReference就是存(值, stamp版本号)解决 ABA。2. 循环自旋消耗 CPUCAS 失败会循环重试自旋如果并发极高大量线程一直 CAS 失败无限循环CPU 飙升。优化限制自旋次数、退化为重量级锁JDK 偏向锁 / 轻量级锁里的自适应自旋3. 只能保证一个变量原子性CAS 一次只能操作一个内存变量。如果要同时修改多个变量CAS 无能为力需要锁或者用AtomicReference封装成对象。四、场景示例场景 1计数器AtomicInteger最常用多线程累加统计比如接口请求计数不用synchronizedimport java.util.concurrent.atomic.AtomicInteger; public class CasDemo { // 原子计数器底层CAS static AtomicInteger count new AtomicInteger(0); public static void add() { // count 原子自增 count.getAndIncrement(); } public static void main(String[] args) throws InterruptedException { Thread t1 new Thread(() - { for (int i 0; i 5000; i) add(); }); Thread t2 new Thread(() - { for (int i 0; i 5000; i) add(); }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(count.get()); // 结果一定10000线程安全 } }如果用普通int count不加锁大概率小于 10000.因为count是读 - 改 - 写三步会丢失更新而 CAS 原子操作保证线程安全。场景 2ABA 场景示例AtomicStampedReferenceimport java.util.concurrent.atomic.AtomicStampedReference; public class ABADemo { // 参数初始值初始版本号 static AtomicStampedReferenceInteger ref new AtomicStampedReference(100, 1); public static void main(String[] args) throws InterruptedException { Thread t1 new Thread(() - { int stamp ref.getStamp(); // 获取版本号1 Integer oldVal ref.getReference(); // old100 try { Thread.sleep(1000); // 休眠让t2修改 } catch (InterruptedException e) {e.printStackTrace();} // CAS预期值100新版本1同时校验版本号 boolean ok ref.compareAndSet(oldVal, 200, stamp, stamp1); System.out.println(t1 CAS结果 ok); }); Thread t2 new Thread(() - { int stamp ref.getStamp(); // 100 → 101版本1 ref.compareAndSet(100,101, stamp, stamp1); // 101 → 100版本再加1 ref.compareAndSet(101,100, ref.getStamp(), ref.getStamp()1); }); t1.start(); t2.start(); } }运行结果t1 CAS结果false虽然值变回 100但是版本号已经变成 3t1 持有的版本号还是 1CAS 失败成功规避 ABA。场景 3自己手写简易 CAS模拟注意下面只是伪代码模拟真实 CAS 必须 CPU 硬件指令Java 代码无法实现真正原子性// 模拟CAS逻辑 public boolean cas(int expect, int newValue){ if (this.value expect) { this.value newValue; return true; } return false; }这个模拟代码不是原子的比较和赋值中间可以被线程打断不是真正 CAS仅用来理解逻辑。五、CAS vs synchronizedCAS (乐观锁)synchronized (悲观锁)锁思想不加锁假设冲突少失败重试认为会冲突直接锁住底层CPU 原子指令OS 互斥锁JDK6 后有偏向 / 轻量锁底层也用到 CAS开销无内核态切换自旋高时 CPU 高竞争大时阻塞线程挂起唤醒开销大适用场景并发冲突少并发冲突激烈JDK6 之后 synchronized 优化偏向锁、轻量级锁底层就是用 CAS竞争激烈膨胀成重量级锁。六、业务上什么时候用 CAS✅ 适合读多写少并发冲突概率低接口 QPS 计数器、埋点统计简单状态标记比如「0 未初始化1 已初始化」防止重复初始化双重检查锁 DCL 也用到 CAS 思想并发容器ConcurrentHashMap更新节点、ConcurrentLinkedQueue无锁队列底层大量 CAS❌ 不适合高并发写、大量线程争抢同一个变量会大量自旋CPU 打满此时用 synchronized 或者锁更好。总结CAS 是比较并交换硬件原子指令实现乐观锁比较内存值和预期旧值相等则更新失败自旋重试存在 ABA、CPU 自旋、只能单变量原子性三个问题适合读多写少场景Atomic 原子类底层依赖 CAS。

相关新闻

香港489条码怎么申请?

香港489条码怎么申请?

一、香港489条码是什么?有什么用? 489条码是由香港货品编码协会直接发行的商品条码前缀,以「489」开头的条码号段仅授权给该协会的正式会员使用。它属于GS1全球标准体系的一部分,适用于零售结算、仓储管理、物流追踪及跨境电商平台…

2026/10/12 13:23:11 阅读更多 →
上下文模式:从传参地狱到链路级数据共享的工程实践

上下文模式:从传参地狱到链路级数据共享的工程实践

在服务端开发里摸爬滚打一段时间后,你会发现很多“设计模式”其实并不高深,它们不过是对日常困境的高度提炼。今天想聊的context-mode,我更喜欢叫它“上下文模式”,就是这么一种东西。我第一次真正重视它,是在一个多租…

2026/10/11 1:25:33 阅读更多 →
superpowers插件:给Claude Code装一套AI技能系统

superpowers插件:给Claude Code装一套AI技能系统

如果你最近在用 Claude Code 写代码,应该没少刷到 superpowers 这个名字。这不是又一个“精选提示词”网站,也不是玄学调参或者魔法脚本,它是给 Claude Code 装进一套“技能系统”的插件:通过官方 plugin 机制,把一批结…

2026/10/11 6:02:35 阅读更多 →

最新新闻

小程序自定义导航栏全攻略:从高度计算到组件封装

小程序自定义导航栏全攻略:从高度计算到组件封装

自定义导航栏,是小程序开发里绕不过去的一道坎。把navigationStyle设置为custom只需要一行配置,但背后要处理状态栏高度、胶囊按钮测量、标题居中、真机适配这一堆事情。这篇笔记是实际项目里反复调试后整理的,横向对比了几种实现思路&#x…

2026/10/12 13:22:35 阅读更多 →
将 Stripe API 与智能体工具链无缝集成:用 TaoToken 统一 Key 打通支付回调与工具调用

将 Stripe API 与智能体工具链无缝集成:用 TaoToken 统一 Key 打通支付回调与工具调用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 13:22:34 阅读更多 →
Android bindService底层原理与实战排错指南

Android bindService底层原理与实战排错指南

1. 从“服务不可用”报错切入:为什么bindService总在onServiceConnected之前失败?你有没有遇到过这样的场景:在Activity里调用bindService(),明明Service已声明、AndroidManifest.xml也配置了intent-filter,可logcat里…

2026/10/12 13:22:34 阅读更多 →
Matt Pocock 怒批“氛围编程“:中文圈最该被这句话打醒的,是那些只会截图晒 Diff 的人

Matt Pocock 怒批“氛围编程“:中文圈最该被这句话打醒的,是那些只会截图晒 Diff 的人

Matt Pocock 怒批"氛围编程":中文圈最该被这句话打醒的,是那些只会截图晒 Diff 的人 【免费下载链接】skills Skills for Real Engineers. Straight from my .agents directory. 项目地址: https://gitcode.com/GitHub_Trending/skills13/sk…

2026/10/12 13:22:34 阅读更多 →
蓝鲸 CMDB 资源池主机查询接口(list_resource_pool_hosts)实战解析:参数、过滤语法与源码实现

蓝鲸 CMDB 资源池主机查询接口(list_resource_pool_hosts)实战解析:参数、过滤语法与源码实现

后端企业应用运维 【免费下载链接】bk-cmdb 蓝鲸智云配置平台(BlueKing CMDB) 项目地址: https://gitcode.com/gh_mirrors/bk/bk-cmdb 点击查看 免费下载 本文以蓝鲸智云配置平台(BlueKing CMDB,仓库目录 bk-cmdb)对外提供的资源…

2026/10/12 13:22:34 阅读更多 →
Vue实战进阶:从环境配置到动态路由与多端部署要点

Vue实战进阶:从环境配置到动态路由与多端部署要点

学Vue这几年,从最开始只会照着教程敲todo list,到后来完整负责过好几个基于Spring Boot加Vue的前后端分离项目,中间踩过的坑、绕过的弯,攒下来不少东西。这份Vue网站制作学习心得,我按“从入门到实战的进阶之路”来写&…

2026/10/12 13:21:33 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →