atomicinteger的cas无锁操作依赖cpu原子指令(如x86的cmpxchg)、volatile保证可见性及unsafe类封装,通过自旋重试实现乐观锁,三者缺一不可。

AtomicInteger 的 CAS 无锁操作底层不靠 Java 代码实现,而是依赖 JVM 调用 CPU 级别的原子指令(如 cmpxchg),配合 volatile 变量语义和 Unsafe 类封装完成。
核心依赖:Unsafe 类与 volatile 字段
AtomicInteger 内部持有一个 volatile int value,保证可见性;所有原子操作都通过私有静态 final 的 Unsafe 实例发起。Unsafe 提供了直接内存操作能力,其中 compareAndSwapInt 是 CAS 的入口方法。
-
value字段被声明为volatile,确保每次读取都是最新值,写入立即刷新到主内存 -
Unsafe.compareAndSwapInt(this, valueOffset, expect, update)是真正执行 CAS 的本地方法,valueOffset是 value 字段在对象内存中的偏移量(由 Unsafe.objectFieldOffset 获取) - 该方法最终编译为一条 CPU 指令(如 x86 下的
lock cmpxchg),具备原子性:比较并交换一步完成,不可中断
CAS 循环逻辑:自旋重试而非阻塞
以 incrementAndGet() 为例,它不是“直接加1”,而是用循环 + CAS 实现:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 先用
getIntVolatile()读当前值 - 计算新值(如 +1)
- 调用
compareAndSwapInt尝试更新:仅当当前值仍等于刚读出的值时才成功 - 失败则重读、重算、重试,直到成功为止 —— 这就是典型的“乐观锁”自旋策略
为什么需要 Unsafe?Java 层无法直接写原子指令
Java 语言规范不暴露底层硬件指令,CAS 必须由 JVM 提供支持。Unsafe 是 JVM 内部机制的桥梁:
- 它绕过 Java 访问控制(如 private 字段),允许直接操作对象字段内存地址
- 其
compareAndSwapXxx方法是 native 实现,在 HotSpot 中对应unsafe.cpp和汇编 stub(如os_cpu/linux_x86/vm/os_linux_x86.cpp) - 不同 CPU 架构(x86/ARM)下,JVM 会生成对应平台的原子指令,屏蔽硬件差异
不是纯“无锁”:底层仍有 lock 前缀或内存屏障
所谓“无锁”是指不使用 synchronized 或 AQS 等操作系统级互斥锁,但并非没有硬件级同步开销:
- x86 上
cmpxchg默认带lock前缀,会锁定缓存行或总线,阻止其他核并发修改同一内存位置 - ARM 等架构用 LDXR/STXR 指令对,配合内存屏障(如
DMB)保证顺序性 - JVM 在 Unsafe 调用前后还会插入必要的内存屏障(如 LoadLoad、StoreStore),配合 volatile 语义防止指令重排序
不复杂但容易忽略:CAS 正确性 = volatile 可见性 + Unsafe 原子指令 + 自旋重试逻辑三者缺一不可。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










