什么是 CAS?并发编程的 “无锁基石”
一、前言在 Java 并发编程的世界里我们总是在和 “线程安全”“性能优化” 打交道。传统的锁机制虽然能解决线程安全问题但也带来了不少性能损耗。而今天要介绍的 Compare and Swap简称 CAS作为无锁编程的核心思想正在为高并发场景提供更高效的解决方案。本文将从锁的困境出发带你全面认识 CAS 的本质、原理、特性并通过实战代码验证其价值。二、并发编程中的“锁”困境在接触 CAS 之前我们先思考一个经典问题如何实现一个线程安全的计数器很多开发者首先会想到使用 synchronized 关键字它就像一把 “排他锁”能保证同一时间只有一个线程执行临界区代码。比如下面这段简单的实现/** * 基于synchronized的线程安全计数器 */ public class SynchronizedCounter { private int count 0; // 加锁保证计数操作的原子性 public synchronized void increment() { count; } public int getCount() { return count; } }这段代码确实能保证线程安全但 synchronized 尤其是早期 JDK 中的重量级锁存在明显的问题1. 传统 synchronized 锁的核心问题性能开销大当线程获取锁失败时会被阻塞并进入等待状态这涉及到操作系统的线程上下文切换。上下文切换需要保存当前线程的执行状态、恢复目标线程的执行状态这个过程会消耗大量的 CPU 资源在高并发场景下频繁的上下文切换会严重拖累系统性能。排他性导致并发效率低synchronized 是排他锁即使多个线程只是读取共享变量也会被串行化执行JDK1.6 后虽有优化但本质仍是排他性锁的核心逻辑。这种串行化执行无法充分利用多核 CPU 的并行处理能力在高并发读写场景下性能瓶颈会非常明显。2. 无锁编程的优势为了解决锁机制的痛点无锁编程应运而生。它的核心优势在于无需加锁和解锁操作减少了锁相关的性能开销线程不会被阻塞避免了上下文切换的损耗能充分利用多核 CPU 的并行能力提升高并发场景下的处理效率。而 CAS正是无锁编程的 “基石”几乎所有的 Java 无锁并发工具都是基于 CAS 思想实现的。三、CAS 的核心定义与工作原理CAS即比较并交换是一种基于硬件实现的原子操作它能在无锁的情况下保证共享变量操作的原子性。1. CAS 三要素要理解 CAS 的工作原理首先要明确它的三个核心参数缺一不可内存地址 V表示要操作的共享变量在内存中的存储地址可以简单理解为这个共享变量本身预期原值 A表示线程在操作共享变量前读取到的该变量的预期值新值 B表示线程想要将共享变量更新后的目标值。2. CAS 核心逻辑CAS 的执行逻辑可以用一句话概括仅当内存地址 V 对应的实际值与线程持有的预期原值 A 完全相等时才将 V 的值原子性地更新为新值 B如果不相等则说明该共享变量已经被其他线程修改过当前线程不执行任何更新操作直接返回失败。整个 CAS 操作是一个原子性的操作由硬件层面保证其不可分割也就是说在 CAS 操作执行期间不会被其他线程打断这是它能保证线程安全的核心原因。3. 通俗举例用生活场景类比 CAS为了让大家更好地理解我们用一个生活中常见的 “多人抢限量商品” 场景来类比 CAS假设某电商平台有 1 件限量商品对应内存地址 V你在下单前看到商品库存是 1对应预期原值 A你准备下单购买此时你期望将库存更新为 0对应新值 B。CAS 成功场景当你发起下单请求时系统检查商品库存V确实是 1和你的预期 A 一致于是立即将库存更新为 0新值 B你成功抢到商品CAS 操作执行成功CAS 失败场景在你发起下单请求的瞬间另一个用户已经先你一步完成下单商品库存V已经被更新为 0和你的预期 A1 不一致系统不会执行任何更新操作你收到 “商品已售罄” 的提示CAS 操作执行失败。这个过程中系统没有给商品加 “锁”不需要等待其他用户操作完成而是通过 “比较 - 交换” 的原子操作实现了库存更新的线程安全这就是 CAS 的核心思想。四、CAS 的核心特性CAS 能成为无锁编程的核心得益于它的三个关键特性这些特性也是它与传统锁机制的核心区别1. 原子性这是 CAS 的核心特性由 CPU 的原子指令直接支撑后续文章会详细讲解。CAS 操作的 “比较” 和 “交换” 是一个不可分割的整体在操作完成前不会被任何其他线程中断这保证了共享变量操作的线程安全无需额外的锁机制保护。2. 无锁性CAS 操作全程不需要获取和释放锁线程在执行 CAS 操作时不会因为竞争资源而被阻塞。即使 CAS 操作失败线程也可以选择重试或放弃操作整个过程没有锁的上下文切换开销这是 CAS 性能优于传统锁的关键原因。3. 乐观性CAS 是一种 “乐观锁” 思想的实现注意乐观锁并非实际意义上的锁而是一种并发控制策略。它的核心假设是大多数情况下共享变量的并发冲突是很少发生的。基于这个假设CAS 不会预先阻塞线程而是直接尝试更新共享变量。只有当检测到共享变量被其他线程修改比较失败时才会处理冲突重试或放弃。这种 “先尝试失败再处理” 的策略在低冲突场景下性能远高于传统的 “先加锁再执行” 的悲观锁策略。五、入门实践Java JDK 的 java.util.concurrent.atomic 包下提供了一系列基于 CAS 实现的原子类 AtomicInteger 就是其中最常用的一个它能保证整数类型变量的原子性操作。下面我们通过实战代码对比 synchronized 和 AtomicInteger 的实现直观感受 CAS 的优势。1. AtomicInteger 的核心 CAS 方法AtomicInteger 提供了 compareAndSet(int expect, int update) 方法这是它的核心 CAS 方法方法含义如下expect预期的共享变量原值对应 CAS 三要素中的 Aupdate想要更新的新值对应 CAS 三要素中的 B返回值boolean 类型 true 表示 CAS 更新成功 false 表示更新失败。此外 AtomicInteger 还提供了 incrementAndGet() 原子自增并返回新值、 getAndIncrement() 原子自增并返回旧值等常用方法这些方法底层都是基于 CAS 实现的。2. 代码示例实现线程安全的计数器我们分别用 synchronized 和 AtomicInteger 实现计数器并在高并发场景下测试它们的性能和线程安全性。示例 1基于 synchronized 的计数器对照组import java.util.concurrent.CountDownLatch; /** * 基于synchronized的线程安全计数器对照组 */ public class SynchronizedCounterTest { // 计数器初始值 private static SynchronizedCounter counter new SynchronizedCounter(); // 线程数模拟高并发场景 private static final int THREAD_NUM 1000; // 每个线程执行的计数次数 private static final int INCR_NUM 1000; // 倒计时门栓用于等待所有线程执行完成 private static CountDownLatch countDownLatch new CountDownLatch(THREAD_NUM); public static void main(String[] args) throws InterruptedException { // 记录开始时间 long startTime System.currentTimeMillis(); // 创建并启动线程 for (int i 0; i THREAD_NUM; i) { new Thread(() - { try { // 每个线程执行1000次自增操作 for (int j 0; j INCR_NUM; j) { counter.increment(); } } finally { // 线程执行完成门栓计数减1 countDownLatch.countDown(); } }).start(); } // 等待所有线程执行完成 countDownLatch.await(); // 记录结束时间 long endTime System.currentTimeMillis(); // 输出结果 System.out.println(基于synchronized的计数器最终值 counter.getCount()); System.out.println(执行耗时 (endTime - startTime) 毫秒); } /** * 基于synchronized的计数器实现 */ static class SynchronizedCounter { private int count 0; public synchronized void increment() { count; } public int getCount() { return count; } } }示例 2基于 AtomicInteger 的计数器试验组CAS 实现import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; /** * 基于AtomicInteger的线程安全计数器试验组CAS实现 */ public class AtomicIntegerCounterTest { // 计数器初始值基于AtomicInteger实现 private static AtomicInteger atomicInteger new AtomicInteger(0); // 线程数与对照组保持一致 private static final int THREAD_NUM 1000; // 每个线程执行的计数次数与对照组保持一致 private static final int INCR_NUM 1000; // 倒计时门栓与对照组保持一致 private static CountDownLatch countDownLatch new CountDownLatch(THREAD_NUM); public static void main(String[] args) throws InterruptedException { // 记录开始时间 long startTime System.currentTimeMillis(); // 创建并启动线程 for (int i 0; i THREAD_NUM; i) { new Thread(() - { try { // 每个线程执行1000次原子自增操作 for (int j 0; j INCR_NUM; j) { // incrementAndGet()原子自增底层基于CAS实现 atomicInteger.incrementAndGet(); } } finally { // 线程执行完成门栓计数减1 countDownLatch.countDown(); } }).start(); } // 等待所有线程执行完成 countDownLatch.await(); // 记录结束时间 long endTime System.currentTimeMillis(); // 输出结果 System.out.println(基于AtomicInteger的计数器最终值 atomicInteger.get()); System.out.println(执行耗时 (endTime - startTime) 毫秒); } }3. 运行结果分析我们分别运行上述两段代码得到的典型结果如下不同机器配置下耗时略有差异但趋势一致运行结果 1基于 synchronized 的计数器基于synchronized的计数器最终值1000000 执行耗时85 毫秒运行结果 2基于 AtomicInteger 的计数器基于AtomicInteger的计数器最终值1000000 执行耗时12 毫秒从结果中我们可以得出两个关键结论线程安全性验证两段代码的计数器最终值都等于 1000*10001000000 说明 synchronized 和 AtomicInteger 都能保证线程安全避免了并发场景下计数丢失的问题性能优势验证基于 CAS 实现的 AtomicInteger 执行耗时远低于基于 synchronized 的计数器这充分体现了 CAS 无锁编程在高并发场景下的性能优势。此外我们还可以直接使用 AtomicInteger 的 compareAndSet 方法手动实现 CAS 操作代码示例如下import java.util.concurrent.atomic.AtomicInteger; /** * 手动使用AtomicInteger的compareAndSet方法实现CAS操作 */ public class CASManualDemo { public static void main(String[] args) { AtomicInteger atomicInteger new AtomicInteger(10); // 第一次CAS操作预期值10新值20 boolean firstCas atomicInteger.compareAndSet(10, 20); System.out.println(第一次CAS操作是否成功 firstCas); System.out.println(CAS操作后的值 atomicInteger.get()); // 第二次CAS操作预期值10与当前实际值20不一致新值30 boolean secondCas atomicInteger.compareAndSet(10, 30); System.out.println(第二次CAS操作是否成功 secondCas); System.out.println(CAS操作后的值 atomicInteger.get()); } }运行结果第一次CAS操作是否成功true CAS操作后的值20 第二次CAS操作是否成功false CAS操作后的值20这个示例直观地验证了 CAS 的核心逻辑只有预期值与实际值一致时才能完成更新操作。六、总结CAS 作为无锁编程的核心思想以 “原子性、无锁性、乐观性” 为核心特性解决了传统锁机制的性能损耗与并发效率问题是 Java 高并发场景下实现线程安全与性能优化的关键技术而atomic包下的原子类如AtomicInteger则是 CAS 思想在 Java 中的便捷落地载体在高并发计数器等场景中具有显著的性能优势。

相关新闻

导师推荐!8款AI论文平台测评:本科生写论文怎么选?

导师推荐!8款AI论文平台测评:本科生写论文怎么选?

导师推荐!8款AI论文平台测评:本科生写论文怎么选? 2026年AI论文平台测评:为何要关注这些工具? 随着人工智能技术的不断进步,越来越多的本科生开始借助AI论文平台提升写作效率与学术质量。然而,面…

2026/7/3 14:41:03 阅读更多 →
心电辅助诊断-体检表格智能识读系统的设计与实现

心电辅助诊断-体检表格智能识读系统的设计与实现

文章目录 一、项目技术二、项目内容和功能介绍三、核心代码四、效果图五 、资料获取 一、项目技术 开发语言:Python python框架:Django 软件版本:python3.7/python3.8 数据库:mysql 5.7或更高版本 数据库工具:Navicat…

2026/7/3 14:41:03 阅读更多 →
基于ssm社区老人健康服务跟踪系统l54o0ud2(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

基于ssm社区老人健康服务跟踪系统l54o0ud2(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表 开题报告内容 基于SSM的社区老人健康服务跟踪系统开题报告 一、选题背景与意义 选题背景 随着全球人口老龄化的加速推进,我国老年人口比例持续上升,社区老年人的健康问题日益成为社会关注的焦点。传统的社区健康服务模式存在诸多弊…

2026/7/3 14:41:07 阅读更多 →

最新新闻

WorkFlow入门Step.1—My Frist WorkFlow Trip!

WorkFlow入门Step.1—My Frist WorkFlow Trip!

自从上次书写的关于《AgileEAS.NET平台开发Step By Step系列-药店系统-索引》使用AgileEAS.NET 敏捷软件开发平台之后,封笔了一段时间,一是最近比较忙,给客户指导培训,通过近20多天的时间,也是开发了一个建议的ERP系统…

2026/7/4 20:43:44 阅读更多 →
Microsoft NLayerApp案例理论与实践 - 基础结构层(Cross-Cutting部分)

Microsoft NLayerApp案例理论与实践 - 基础结构层(Cross-Cutting部分)

NLayerApp中IoC容器的实现 在应用程序设计的过程中,我们会基于这样一个设计准则,就是类型之间的关联应该依赖于接口或者抽象,而非具体的实现。这样就使得我们能够在保证整个程序结构不变的情况下,很方便地替换组件的具体实现方式…

2026/7/4 20:43:44 阅读更多 →
E-Hentai漫画批量下载:3步解锁你的个人数字图书馆

E-Hentai漫画批量下载:3步解锁你的个人数字图书馆

E-Hentai漫画批量下载:3步解锁你的个人数字图书馆 你是否曾在深夜浏览E-Hentai时,发现心仪的漫画集却苦于无法一次性保存?或者因为网络不稳定而不得不反复刷新页面,只为下载那几张珍贵的图片?今天,让我带你…

2026/7/4 20:43:44 阅读更多 →
DWT硬件延时

DWT硬件延时

1、Cortex-M4内核架构2、硬件延时利用计数功能的硬件进行延时,比如单片机片上定时器(Timer),内核滴答定时器(systick)等:__weak void HAL_IncTick(void) {uwTick; } __weak uint32_t HAL_GetTick(void) {return uwTick…

2026/7/4 20:41:43 阅读更多 →
如何通过5个简单步骤实施HARA

如何通过5个简单步骤实施HARA

确保汽车系统的安全性并非易事。随着现代车辆日益复杂,识别并减轻潜在危险变得比以往任何时候都更加关键。这正是危害分析与风险评估(HARA)发挥作用的地方。 HARA是一种结构化方法,旨在评估风险并制定符合ISO 26262(汽…

2026/7/4 20:41:43 阅读更多 →
合同管理系统的实施-开发费用问题

合同管理系统的实施-开发费用问题

此前《从纸质台账到数智中台:合同管理系统的演进与未来》一文,梳理了合同管理系统的发展脉络。从功能迭代角度来看,合同管理系统是依托 OA 无纸化办公、企业信息化的基础需求,逐步拆分独立出来的专业化管理软件。在专业化演变进程…

2026/7/4 20:39:43 阅读更多 →

日新闻

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 正式发布,这是一个关键的安全修复版本,修复了多个方面的问题,还对部分功能进行了优化。 安全修复亮点 此次发布在安全修复上表现突出。binprot 避免了项目引用计数溢出,mcmc 因安全问题提升了上游版本号&#xf…

2026/7/4 0:04:29 阅读更多 →
终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案 【免费下载链接】HMCL A Minecraft Launcher which is multi-functional, cross-platform and popular 项目地址: https://gitcode.com/gh_mirrors/hm/HMCL HMCL(Hello Minecraft! Lau…

2026/7/4 0:06:29 阅读更多 →
KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

1. KMX63与PIC18F66K40的硬件协同架构解析KMX63作为一款三轴加速度计和磁力计组合传感器,与PIC18F66K40微控制器的搭配堪称嵌入式HMI开发的黄金组合。这套硬件组合的核心优势在于KMX63提供的高精度运动感知能力与PIC18F66K40强大的信号处理能力形成了完美互补。KMX6…

2026/7/4 0:06:29 阅读更多 →

周新闻

月新闻