Java CAS 底层汇编指令 lock cmpxchg 怎么懂

胖墨同学_8051

胖墨同学_8051

2026-08-07

930人浏览

原创

lock cmpxchg 是 x86 平台上 cas 的原子指令,其中 cmpxchg 完成比较并交换,lock 前缀保障多核缓存一致性;它不可分割、失败返回旧值,且必须配合 volatile 保证可见性。

java cas 底层汇编指令 lock cmpxchg 怎么懂

CAS 的底层汇编指令 lock cmpxchg 不是 Java 程序员直接写的代码,而是 JVM 在调用 Unsafe.compareAndSwapInt 等方法时,由 HotSpot 编译器在 x86_64 平台上自动生成的机器级指令。理解它,关键不是背指令格式,而是抓住“为什么加 lock”和“cmpxchg 干了什么”这两点。

lock cmpxchg 的三个核心作用

lock cmpxchg 是一条复合指令:cmpxchg 负责“比较并交换”,lock 前缀负责多核环境下的执行保障。它不是两步操作,而是一条原子指令:

  • cmpxchg:把内存地址里的值读出来,跟寄存器中的“预期值”比较;相等就写入“新值”,不等就不写;整个过程不可拆分,硬件保证中间不被中断
  • lock 前缀:告诉 CPU:“这条指令访问的内存地址,必须独占访问”。它不锁整个系统,也不锁整条总线,而是触发缓存一致性协议(如 MESI),确保其他 CPU 核心不能同时修改同一缓存行
  • 失败返回机制:指令执行完,CPU 自动把内存原值放进 rax 寄存器(x86 下),Java 层据此判断是否成功——成功返回 true,失败返回 false,并暴露旧值供上层重试

为什么不能只写 cmpxchg,非要加 lock?

单核时代,cmpxchg 本身就能保证原子性;但在多核环境下,没有 lock,两个核心可能同时读到同一个旧值、都判断为“相等”、都写入新值——结果变成覆盖式更新,CAS 就失效了。

lock 的实际效果取决于硬件状态:

Java Maven Code Review
Java Maven Code Review

审查Java Maven项目(ZIP压缩包或GitLab仓库URL),检查代码规范、命名、模块边界、可维护性问题以及重复代码。

下载
  • 如果目标变量已在本核 cache 中且处于 Exclusive 或 Modified 状态 → 直接本地完成,走缓存锁(Cache Locking),开销极小
  • 如果该变量在其他核 cache 里是 Shared 状态 → 本核发起 RFO(Request For Ownership)请求,强制其他核失效对应缓存行 → 仍是缓存行级控制,不锁总线
  • 只有在极特殊场景(比如访问 uncached 内存、跨缓存行对齐)→ 才退化为总线锁(Bus Locking),现代 CPU 几乎不会发生

Java 层怎么“看到”这条指令?

你写 atomicInteger.compareAndSet(1, 2),JVM 实际做了这些事:

  • 通过 Unsafe 调用 JVM 内建的原子函数(如 Atomic::cmpxchg)
  • JIT 编译器识别该调用,在生成本地代码时插入 lock cmpxchg 指令(x86 下)或对应平台指令(ARM 是 ldaxr/stlxr)
  • 指令执行后,JVM 把 CPU 返回的状态(ZF 标志位 + rax 中的旧值)转成 Java 的 boolean 和语义逻辑

你不需要手写汇编,但可以通过 -XX:+PrintAssembly 参数让 JVM 输出热点方法的汇编,搜 lock cmpxchg 就能看到它真实出现在哪一行。

真正影响性能的关键点不在指令本身

懂了 lock cmpxchg 是什么,下一步要关注它在实际并发中怎么“出问题”:

  • 伪共享(False Sharing):多个原子变量挨得太近,落在同一缓存行里,一个被改,整行失效,导致其他核频繁同步 → 解决办法是用 @Contended 或手动 padding
  • 自旋空转:CAS 失败后循环重试,若竞争激烈,会浪费大量 CPU 时间 → 应结合退避策略(如 Thread.onSpinWait())或换用锁
  • ABA 问题:值从 A→B→A,CAS 误判为“没变” → 需用 AtomicStampedReference 加版本戳
  • volatile 必须配合:CAS 变量必须声明为 volatile,否则其他线程看不到最新值,CAS 会基于过期值重试 → 这不是 lock 指令的事,是内存可见性问题

指令本身很稳定,真正决定 CAS 是否高效、是否安全的,是你的数据布局、重试逻辑和内存模型理解。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

java

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

9877

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

7022

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

6192

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1064

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

888

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1296

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2589

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

19931

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1155

8

热门下载

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

精品课程

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

共0课时 | 0人学习

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

共0课时 | 0人学习