volatile通过内存屏障约束指令重排序:写前加storestore、写后加storeload、读前加loadload、读后加loadstore,并依托happens-before规则实现跨线程有序性,不加锁但仅保障自身相关指令顺序。

volatile 不是直接“禁止”编译器重排序,而是通过插入内存屏障(Memory Barrier)向 JVM 和底层硬件发出明确的顺序约束,让相关指令不能跨屏障移动,从而在多线程场景下保障逻辑上的有序性。
靠内存屏障限制指令移动范围
JVM 在生成字节码或 JIT 编译为机器码时,对 volatile 变量的读写操作自动插入四类屏障:
- 写操作前插入 StoreStore 屏障:确保该写之前的所有普通写操作,不会被重排到它之后
- 写操作后插入 StoreLoad 屏障:阻止后续的读操作被提前到该写之前执行
- 读操作前插入 LoadLoad 屏障:保证该读之前的所有普通读操作,不会被重排到它之后
- 读操作后插入 LoadStore 屏障:防止后续的写操作被提前到该读之前
依托 happens-before 规则建立执行顺序
volatile 变量规则是 Java 内存模型(JMM)定义的核心 happens-before 关系之一:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 对一个 volatile 变量的写操作 happens-before 后续对该变量的读操作
- 这个“后续”不要求代码紧邻,只要读发生在写之后(逻辑上或实际执行中)就成立
- 该规则跨线程生效,配合程序次序规则和传递性,可推导出更长的可见性链
不依赖锁,但有明确边界
与 synchronized 不同,volatile 不加锁、不阻塞、不涉及上下文切换,但它对重排序的约束仅作用于自身读写相关的指令:
- 只约束 volatile 读/写与它前后普通读写的相对顺序
- 不保证全局所有指令的绝对顺序,也不影响无关变量之间的重排
- 例如:x = 1; flag = true;(flag 是 volatile),那么 x=1 一定在 flag=true 之前对其他线程可见
底层靠 lock 指令触发硬件同步
在 x86 平台,volatile 写通常编译为带 lock 前缀的指令(如 lock addl $0x0,(%rsp)),它会强制:
- 将当前 CPU 缓存行数据立即写回主内存
- 使其他 CPU 中对应缓存行失效
- 形成天然的执行顺序锚点,阻止处理器乱序执行跨越该指令
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










