volatile保证可见性和禁止指令重排序,但不保证原子性;它使线程修改立即写入主内存、读取强制从主内存加载,适用于状态标志、DCL单例instance等一写多读场景。

volatile 不实现线程同步,它只保证变量的可见性和禁止指令重排序,不能保证原子性。
volatile 解决的是可见性问题
当一个线程修改了被 volatile 修饰的变量,新值会立即写入主内存;其他线程读取该变量时,会直接从主内存读取最新值,而不是使用本地工作内存中的旧副本。
这避免了因线程缓存导致的“读不到最新值”的问题,但不等于“多个线程能安全地共同修改它”。
volatile 无法保证复合操作的原子性
例如:i++(等价于 read-modify-write)包含三步:读取 i、加 1、写回 i。即使 i 是 volatile,这三个步骤仍可能被其他线程穿插执行,结果不可预期。
立即学习“Java免费学习笔记(深入)”;
常见误用场景:
- 用 volatile int count++; 实现计数器 → 错误,结果可能丢失
- 用 volatile boolean flag = true; 控制循环开关 → 正确,单次写+多次读,无竞态
volatile 的底层机制依赖内存屏障和 Happens-Before 规则
JVM 在编译 volatile 读写时,会插入特定的内存屏障(Memory Barrier),确保:
- 写 volatile 变量前,所有之前的读写操作必须已完成(禁止重排序到其后)
- 读 volatile 变量后,所有之后的读写操作不能提前(禁止重排序到其前)
- 写操作刷新到主内存,读操作强制从主内存加载
这些保障由 JVM 和 CPU 共同协作完成,是硬件级优化支持的轻量机制,开销远小于 synchronized 或 Lock。
适用 volatile 的典型场景
适合“一写多读”,且写操作本身是原子的场景:
- 状态标志位:volatile boolean isRunning = true;
- 单例模式中双重检查锁的 instance 引用(防止指令重排导致未初始化对象被返回)
- 与 CAS 配合使用的变量(如 AtomicInteger 内部 value 字段)
只要不涉及“读-改-写”链式操作,volatile 就是高效、安全的选择。


















