程序次序规则是JMM对单线程内操作顺序的语义承诺,禁止编译器和处理器重排序,保障源码顺序执行;它仅限同一线程内有效,不解决跨线程可见性问题。

程序次序规则本身不用于“保证”单线程执行顺序,而是对单线程内已有顺序的一种语义描述和保障承诺。在单线程中,代码天然按书写顺序执行(即“as-if-serial”语义),无需额外操作来“实现”顺序——它本来就是确定的。
程序次序规则的本质是约束JVM优化行为
该规则指出:在一个线程内,按照程序控制流顺序,书写在前面的操作先行发生于书写在后面的操作。这不是运行时调度指令,而是Java内存模型(JMM)为编译器和处理器设定的一条禁止重排序边界。它的实际作用是:
- 阻止编译器将后置语句提前到前置语句之前(如把赋值a=1移到if判断前,当该if依赖a的旧值时)
- 阻止CPU指令乱序执行破坏逻辑依赖(例如先写flag = true,再写data = 42;若无约束,可能flag先被其他线程看到而data还未写入)
- 确保单线程内的观察结果始终符合源码顺序,哪怕底层做了优化
它不解决多线程间的顺序问题
程序次序规则只在同一个线程内部有效。它不能保证另一个线程看到这些操作的顺序,也不能强制两个线程之间的执行先后。比如:
Thread A:
x = 1;
flag = true;
Thread B:
if (flag) System.out.println(x);
即使A中x=1在flag=true之前,B仍可能打印0或什么也不打印——因为程序次序规则不跨线程生效。这时需用volatile、synchronized等建立跨线程的happens-before关系。
日常编码中你其实已经在依赖它
不需要显式调用或配置程序次序规则。只要没用到volatile/synchronized等同步机制,JVM就默认遵守该规则来维持单线程正确性。典型场景包括:
- 方法内局部变量赋值与后续使用(int a = 5; return a * 2;)
- 构造函数中字段初始化与this引用逸出检查(new X()过程中,字段写入一定发生在构造结束前)
- if/for/while等控制结构的条件判断与分支体执行顺序
一旦引入共享变量或并发访问,仅靠程序次序规则就不够了,必须配合其他happens-before规则协同使用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











