volatile不能保证原子性,因为它仅保障单次读/写操作的可见性与有序性,不支持“读—改—写”等多步复合操作;如i++会被拆分为读、加、写三步,无锁机制导致竞态,最终结果可能丢失更新。

volatile 不能保证原子性,因为它只管“单次读”和“单次写”的可见与有序,不管“读—改—写”这类需要多个步骤连贯执行的操作。
volatile 管什么:可见性 + 禁止重排
它确保:一个线程写完 volatile 变量,其他线程立刻能读到新值;编译器和 CPU 不会把对它的读写操作乱序优化。但这些保障仅作用于“一次读”或“一次写”本身,不延伸到跨操作的逻辑链条。
i++ 就是典型的三步非原子操作
哪怕变量声明为 volatile int i = 0,执行 i++ 时仍会分解为:
- 从主内存(或最新缓存)读取 i 的当前值
- 在寄存器中加 1
- 把结果写回主内存
这三步之间没有任何锁定或互斥机制。两个线程可能同时读到 i=5,各自算出 6,再先后写回去——最终 i=6,但两次累加只体现了一次。
底层没提供原子执行能力
volatile 编译后会插入内存屏障(如 StoreLoad),但它不生成 LOCK 前缀指令(像 AtomicInteger.incrementAndGet() 那样),也不调用 CPU 的 CAS(Compare-And-Swap)原语。它只是“告诉别人我改了”,而不是“让我一个人改完再让别人动”。
适用边界很明确
适合用 volatile 的场景,是那些不需要依赖旧值的简单状态切换,比如:
- boolean shutdown = false; → 一个线程设为 true,其他线程检查后退出循环
- int status = INIT; → 状态只写一次,后续只读不改
一旦涉及“先读后写”“计数”“累加”“条件更新”,就必须换方案:synchronized、ReentrantLock 或 AtomicXXX 类。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











