线程启动规则保证主线程调用thread.start()前对共享变量的写入对子线程run()方法首次读取可见;它通过内存屏障实现初始状态快照,不保障后续更新,常与volatile、synchronized等配合扩展可见性。

线程启动规则是 Java 内存模型(JMM)中一条基础但关键的 happens-before 规则:主线程调用 thread.start() 的操作,happens-before 新线程执行其 run() 方法中的任意操作。它不靠“立刻同步”,而是通过建立逻辑上的先行关系,确保启动前已设置的共享状态对子线程可见。
主线程设置的状态,在子线程启动时就“固定可见”
主线程在调用 start() 之前对共享变量的写入,只要发生在 start() 调用前(按程序顺序),就会被 JMM 保证对子线程 run() 中的首次读取可见。这不是靠轮询或延迟,而是 JVM 在线程启动时插入内存屏障,强制将主线程本地缓存中 start() 前的所有写操作刷新到主内存,同时确保子线程从主内存加载初始数据。
- 例如:主线程先设置
config = new Config("prod");,再执行worker.start();—— 子线程 run() 中第一次访问 config,一定能拿到完整初始化后的对象,不会看到 null 或部分构造状态 - 即使编译器或 CPU 对主线程的代码做了重排序,只要重排序不破坏“config 赋值 → start()”的程序顺序,JMM 就仍能保证该 happens-before 关系成立
它只保障“启动那一刻”的快照,不持续同步
该规则只覆盖子线程 run() 方法开始执行时的初始可见性,不负责后续运行期间的状态更新。也就是说:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 主线程在 start() 后再修改共享变量,子线程不一定立即看到——除非引入 volatile、锁或其他 happens-before 链
- 子线程内部对共享变量的修改,主线程在 join() 前也看不到;需依赖线程终止规则或额外同步机制
和 volatile、synchronized 的配合很自然
线程启动规则常作为跨线程通信链的起点,与其他规则组合使用来延长可见性范围:
- 主线程设
data = 100;→ready = true;(ready 是 volatile)→worker.start();:此时 data 和 ready 都对子线程可见,且子线程读到 ready == true 时,也能安全读到 data == 100(借助 volatile 规则传递) - 主线程在 synchronized 块中初始化资源后调用 start(),子线程进入同一把锁的临界区时,不仅能见到初始化结果,还能避免指令重排干扰
这条规则看似简单,却是正确初始化工作线程、传递配置、启动任务的前提。它让开发者无需手动插入屏障或等待,就能获得一次可靠、轻量的跨线程状态交付。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










