jmm不保证复合操作原子性,因其本质是多步指令(读-改-写),易被线程抢占;volatile仅保可见性与有序性,不保原子性;需用atomicxxx类cas或不可变对象+原子引用解决,多变量协同则必须加锁。

JMM 本身不保证复合操作的原子性,它恰恰是通过明确“不保证”来揭示问题——复合操作天然就是非原子的,除非你主动加锁或使用其他同步机制。
复合操作为什么默认非原子
像 i++、list.add(x)、map.put(k, v) 这类操作,在 JVM 层面都由多条指令组成:
- 读取当前值(从主内存加载到工作内存)
- 在工作内存中计算新值
- 把结果写回主内存
这三步之间可能被其他线程抢占。JMM 允许这种交错执行,所以多个线程同时执行 i++,最终结果往往小于预期——这不是 JMM 的“缺陷”,而是它对硬件真实行为的诚实建模。
volatile 无法解决复合操作的非原子性
volatile 只保证单次读/写的可见性和有序性,不保证操作本身的原子性。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 对 volatile int i = 0; 执行 i++,仍是“读-改-写”三步,volatile 只确保每次读都看到最新值、每次写都立即刷出,但中间步骤仍可被中断
- 它能防止指令重排序,但挡不住线程切换
不加锁时想让复合操作“看起来原子”,只有两条路
一是用 AtomicXXX 类提供的 CAS 方法(如 AtomicInteger.updateAndGet、AtomicReference.updateAndGet),它们把整个逻辑封装进一个循环 CAS 中,靠 CPU 硬件指令保障单变量更新的原子性;
二是用 不可变对象 + 原子引用,比如用 AtomicReference
注意:这些方案都只适用于单个共享变量或整体替换场景。涉及多个变量协同修改(如银行转账:A 减、B 加),CAS 无法覆盖,必须用 synchronized 或显式 Lock。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










