程序次序规则指单线程内按控制流顺序,先执行的操作happens-before后执行的操作;它基于语义顺序而非时间先后,不依赖同步机制,是as-if-serial语义的体现,且仅在单线程内有效。

程序次序规则是 happens-before 最基础、最直观的一条规则:在一个线程内部,按照代码的控制流顺序,书写(或逻辑上先执行)的操作 happens-before 书写在它之后的操作。
它不是按“时间先后”而是按“语义顺序”保证可见性
这条规则不依赖锁、volatile 或任何同步机制,它是单线程执行语义的自然延伸。JVM 和 CPU 可以重排序指令,但必须保证重排后的结果与按代码顺序执行的结果一致(as-if-serial 语义)。所以,即使底层执行顺序变了,只要对本线程可见的行为没变,就仍满足 happens-before。
例如:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
-
int a = 1;→int b = a + 2;→System.out.println(b); - a 的赋值 happens-before b 的计算,b 的计算 happens-before println 执行
- 因此 a=1 的结果对 b=a+2 是可见的,无需额外同步
注意“控制流顺序”,不只是“代码行顺序”
它遵循实际执行路径,而非源码物理排列。比如:
- 分支中只走 if 分支,则 if 块内操作 happens-before 后续的公共代码;else 块中的操作不参与该路径的次序链
- 循环体每次迭代内部满足次序规则,但不同迭代之间不自动构成 happens-before(除非有其他规则介入)
- 方法调用中,调用前的表达式求值 happens-before 方法体内第一条语句;方法返回前的最后一步 happens-before 调用点后续语句
它是其他规则传递性的起点
程序次序规则常作为链条的第一环,配合 volatile 规则或锁规则,把单线程内的可见性“传递”到多线程间。典型例子:
- 线程 A 中:
x = 42;→flag = true;(volatile) - 程序次序规则保证 x=42 happens-before flag=true
- volatile 规则保证 flag=true happens-before 线程 B 读 flag
- 传递性得出:x=42 happens-before 线程 B 读 flag → 若 B 读到 true,就能看到 x=42
它只在单线程内有效,跨线程不自动成立
这是最容易忽略的关键点:线程 A 的第 5 行代码 happens-before 它的第 6 行,但和线程 B 的任意一行都没有 happens-before 关系——除非通过锁、volatile、start/join 等显式建立。没有这些桥梁,两个线程就像平行宇宙,彼此看不到对方的写入。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










