Java并发中的CAS机制:原理、应用与挑战(通俗易懂版)
上一期文章内容:Java并发中的乐观锁与悲观锁,
本期文章我们来讲一下Java并发中的CAS机制
一、从银行账户案例理解CAS

CAS 是一种乐观锁机制,用于在不使用锁的情况下实现多线程对共享资源的并发访问。
它包含三个操作数:内存位置(V)、预期原值(A)和新值(B)。
当且仅当内存位置 V 的值等于预期原值 A 时,才将内存位置 V 的值更新为新值 B;
否则,不做任何操作。整个 CAS 操作是原子性的,由 CPU 硬件指令直接支持。
想象这样一个场景:你和朋友同时查看一个银行账户余额为100元,你们都尝试转账。传统做法是银行用"锁"机制,只允许一人操作。而CAS(Compare-And-Swap比较交换)采用更聪明的策略:
你查询当前余额:100元(旧值)
系统记录此刻的版本号为V1
当你提交转账时,系统会检查:
当前余额是否仍是100元?
版本号是否还是V1?
只有当两者都满足时,转账才会成功,并更新版本号为V2
这种无锁机制就像超市自助结账——不需要收银员(锁),顾客(线程)自己完成操作,系统通过版本检查保证安全。
二、Java底层实现揭秘
2.1 神秘的Unsafe类
Java通过sun.misc.Unsafe类实现CAS,这个类就像Java世界的"瑞士军刀",为什么会这么说呢?
因为 sun.misc.Unsafe 类功能强大并且多样,提供了直接操作内存、基于CAS的操作方法、线程调度相关方法等的能力,但是我们在使用时需要持谨慎态度,因为会涉及安全、可移植、代码维护等问题!
public final class Unsafe {// 对象类型CASpublic final native boolean compareAndSwapObject(Object obj, long offset, Object expect, Object update);// int类型CASpublic final native boolean compareAndSwapInt(Object obj, long offset, int expect, int update);// long类型CASpublic final native boolean compareAndSwapLong(Object obj, long offset, long expect, long update);
}
通过JNI调用本地代码,最终映射到CPU指令(如x86的CMPXCHG),整个过程就像:
获取当前值
计算新值
调用CPU指令进行原子比较交换
2.2 AtomicInteger实现解析
以AtomicInteger为例,看Java如何包装CAS:
public class AtomicInteger {private volatile int value; // 保证可见性private static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset; // 内存偏移量static {try {valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}
}
关键点说明:
volatile保证值变更的可见性内存偏移量定位字段位置
CAS失败时自动重试(自旋)
三、CAS的三大挑战与应对
3.1 ABA问题:账户余额的"时空穿越"
假设账户余额变化:100 → 200 → 100
线程A读取100(版本V1)
线程B完成两次修改(V1→V2→V3)
线程A的CAS检查值仍是100,但版本已变化
解决方案: 使用带版本号的AtomicStampedReference
AtomicStampedReference<Integer> account = new AtomicStampedReference<>(100, 0);// 存款操作
int[] stampHolder = new int[1];
int current = account.get(stampHolder);
if(account.compareAndSet(current, current+50, stampHolder[0], stampHolder[0]+1)) {System.out.println("存款成功");
}
3.2 自旋开销:CPU的"空转危机"
当多个线程激烈竞争时,CAS可能导致CPU空转。优化策略:
-
自适应自旋:JVM动态调整自旋次数
-
pause指令:插入CPU提示指令降低功耗
// x86架构实现示例 __asm__ volatile ("pause"); -
退避策略:随机等待后再重试
3.3 多变量原子性:关联操作的困局
需要保证多个变量的原子更新时:
方案一:对象包装
class Account {int balance;int version;
}AtomicReference<Account> atomicAccount = new AtomicReference<>();
方案二:锁机制
synchronized(lock) {account.balance -= amount;account.version++;
}
四、CAS应用场景分析
| 场景 | 适用性 | 示例 |
|---|---|---|
| 计数器 | ★★★★★ | AtomicInteger |
| 状态标志 | ★★★★★ | AtomicBoolean |
| 对象引用更新 | ★★★★☆ | AtomicReference |
| 复杂数据结构 | ★★☆☆☆ | ConcurrentHashMap内部实现 |
| 事务性操作 | ★☆☆☆☆ | 需要结合其他机制 |
五、性能对比:CAS vs 锁
通过JMH基准测试(ops/ms):
| 线程数 | CAS | 同步锁 | ReentrantLock |
| 1 | 15234 | 14567 | 14230 |
| 4 | 12345 | 2345 | 4566 |
| 8 | 9876 | 1023 | 2348 |
结论:
低竞争场景:性能相近
高并发场景:CAS性能优势明显
极端竞争:可能需要退化为锁机制
相关文章:
Java并发中的CAS机制:原理、应用与挑战(通俗易懂版)
上一期文章内容:Java并发中的乐观锁与悲观锁, 本期文章我们来讲一下Java并发中的CAS机制 一、从银行账户案例理解CAS CAS 是一种乐观锁机制,用于在不使用锁的情况下实现多线程对共享资源的并发访问。 它包含三个操作数:内存位置&a…...
腾讯发布混元-3D 2.0: 首个开源高质3D-DiT生成大模型
在之前的文章中已经和大家介绍过腾讯HunYuan-3D 1.0,感兴趣的小伙伴可以点击下面链接阅读~ HunYuan-3D 是首个开源高质3D-DiT生成大模型,几何与纹理解藕生成,一键将创意具象化。 2.0模型架构图及介绍 2.0模型将几何和纹理生成解耦࿰…...
【机器学习】线性回归与一元线性回归
线性回归与一元线性回归 V1.1线性回归问题线性方程的最优解一元线性回归一元线性回归的方程一元线性回归距离衡量方法一元线性回归的最优化求解一元线性回归的最小二乘法解法 V1.1 线性回归问题 线性回归问题就是找一条线或超平面,并使用线或超平面来描述数据分布…...
哈希表-两个数的交集
代码随想录-刷题笔记 349. 两个数组的交集 - 力扣(LeetCode) 内容: 集合的使用 , 重复的数剔除掉,剩下的即为交集,最后加入数组即可。 class Solution {public int[] intersection(int[] nums1, int[] nums2) {Set<Integer…...
望远镜成像系统--科学评价光学镜头
望远镜是一种利用透镜或反射镜以及其他光学器件观测遥远物体的光学仪器。其原理是通过透镜的折射或反射镜的反射,将光线聚焦成像,再经过一个放大目镜进行观察。日常生活中的光学望远镜又称“天文望远镜”。1608年,荷兰的一位眼镜商汉斯利伯希…...
服务器延迟给视频网站造成的影响
在数字化时代中,网络视频已经成为人们日常娱乐和获取信息的重要平台,网络视频的流畅性会影响着用户的体验度,那么,当服务器出现延迟会对视频网站造成哪些影响呢?本文就来共同了解一下吧! 当所使用的服务器由…...
C++算法竞赛基础语法-9
快速排序是一种高效的排序算法,由C. A. R. Hoare在1960年提出,基本思想是分治法(Divide and Conquer)策略,通过递归将一个大问题分解为若干个较小的子问题,然后合并这些子问题的解来解决原始问题 快速排序…...
国产编辑器EverEdit - 极简追梦人的福音:迷你查找
1 迷你查找 1.1 应用场景 某些场景下,用户不希望调出复杂的查找对话框,此时可以使用迷你查找窗口。 1.2 使用方法 选择主菜单查找 -> 迷你查找,或使用快捷键Ctrl Alt F,会在右上角弹出迷你查找窗口,如下图所示…...
Flutter 异步编程利器:Future 与 Stream 深度解析
目录 一、Future:处理单次异步操作 1. 概念解读 2. 使用场景 3. 基本用法 3.1 创建 Future 3.2 使用 then 消费 Future 3.3 特性 二、Stream:处理连续异步事件流 1. 概念解读 2. 使用场景 3. 基本用法 3.1 创建 Stream 3.2 监听 Stream 3.…...
数据结构 day05
数据结构 day05 5. 队列5.3. 链式队列5.3.1. 特征5.3.2. 代码实现 6. 双向链表6.1. 特性6.2. 代码实现 5. 队列 5.3. 链式队列 5.3.1. 特征 逻辑结构:线性结构 存储结构:链式存储 操作:创建、入列、出列、判空、清空 5.3.2. 代码实现 头文…...
股票数据接口API实例代码python、JAVA等多种语言演示免费获取实时数据、历史数据、CDMA、KDJ等指标数据配有API说明文档
本文中所有接口均可直接在浏览器打开获取数据,为了便于大家验证有效性,已经做好了超链接,直接点击即可! 沪深两市股票列表 API接口链接(可点击验证):https://api.mairui.club/hslt/list/b…...
【Map vs Set】:Java数据存储的“双子星”对决
个人主页:♡喜欢做梦 欢迎 👍点赞 ➕关注 ❤️收藏 💬评论 目录 🍰一、搜索 🍮1.概念 🍮2.模型 🍰二、Map 🍨1.什么是Map? 🍨2.Map的实例化 &…...
ollama+langchain+deepseek本机跑通大模型
一、部署deepseek Ollama,这是是一个开源的大语言模型平台,它允许用户在本地环境中运行、创建和共享大型语言模型。Ollama提供了丰富的功能和特性,使得用户可以在自己的计算机上轻松地部署和运行大型语言模型。官网:https://ollam…...
03【FreeRTO队列-如何获取任务信息与队列的动静态创建】
一.利用 vTaskList()以及 vTaskGetRunTimeStats()来获取任务的信息 1.现象与开启启用宏 freeRTOSConfig.h //必须启用 #define configUSE_TRACE_FACILITY 1 #define configGENERATE_RUN_TIME_STATS 1 #define configUSE_STATS_FORMATTING_FUNCTIONS…...
vue-plugin-hiprint (vue2
页面效果 <template><div><div class="d-flex flex-column mt5"><div class="d-flex flex-row " style="margin-bottom: 10px;justify-content: center;"><!-- 纸张大小 A3、A4 等 --><div class="paper…...
【后端面试总结】什么是堆,什么是栈
堆与栈:计算机科学中的两大内存管理利器 在计算机科学中,内存管理是软件开发的核心组成部分之一。其中,堆(Heap)和栈(Stack)是两种最基本的内存分配方式,它们各自有着独特的特性和应…...
第39周:猫狗识别 2(Tensorflow实战第九周)
目录 前言 一、前期工作 1.1 设置GPU 1.2 导入数据 输出 二、数据预处理 2.1 加载数据 2.2 再次检查数据 2.3 配置数据集 2.4 可视化数据 三、构建VGG-16网络 3.1 VGG-16网络介绍 3.2 搭建VGG-16模型 四、编译 五、训练模型 5.1 上次程序的主要Bug 5.2 修改版…...
力扣--239.滑动窗口最大值
问题 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1: 输入:nums [1,3,-1,-3,5,3,6,7], …...
傅里叶变换推导
基本模型 假设在二维直角坐标系中,可以用相互垂直的基向量和表示: 假设: 假设在上的投影为,那么: 所以: 用公式表达: 但是在实际中,基向量和不一定长度都是1,重新推导一…...
扣子工作流中禁止同类别的图像流节点,不能超过4个
一、问题1不能在一个工作流中超过4个图像的并行节点 1、现象 本来想着在扣子中一次生成多张图片。 然后问了扣子小助手 2、图像节点限制 扣子给了如下反馈 近期图像流上线了并发限额,具体规则如下: 针对对象:单用户维度,非 bot…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...
【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
AIGC 基础篇 Python基础 02
1.bool类型 书接上回,我们上次最后讲了三大数据类型,除了这三个之外,Python也有bool类型,也就是True和False。 a 2 print(a1) print(a2) 像这里,输出的内容第一个是False,因为a的值为2,而第…...
