确保任务对象构造完成后再传给thread是根本前提,jmm通过happens-before规则保障start()前的写操作对新线程可见,无需手动内存屏障,有效性应靠逻辑校验而非底层机制。

调用 Thread.start() 前确保任务句柄有效,关键不在于“条件可见性屏障”这种易被误用的术语,而在于**明确控制任务对象生命周期与线程启动时机的耦合关系**。Java 内存模型(JMM)中并无“条件可见性屏障”这一标准机制;真正起作用的是 happens-before 规则 和 构造完成语义——只要任务对象在构造完毕后才被传入线程,且未被提前发布(escape),其字段对新线程天然可见。
任务对象必须在完全构造完成后才交付给 Thread
这是最根本的安全前提。若任务(如 Runnable 实现类)在构造器中尚未初始化完毕就被赋值给成员变量、加入队列或传给 Thread 构造器,新线程可能看到部分初始化状态。
- 避免在构造器中启动线程、注册监听、发布
this引用(如new Thread(this).start()) - 推荐使用静态工厂或构建器模式,确保返回实例前所有字段已安全初始化
- 若任务含可变状态,考虑用
final字段声明不可变依赖,或用volatile/ 锁保护后续修改
Thread 构造与 start() 之间无需额外内存屏障
Thread 构造本身不触发线程执行,仅封装任务和配置;start() 才真正创建 OS 线程并建立 JMM 的 happens-before 边界:主线程中对任务对象的所有写操作,在新线程执行 run() 时一定可见——前提是这些写操作发生在 start() 调用之前,且未被重排序破坏逻辑顺序。
- 只要任务对象引用是通过局部变量或 final 字段传递,JVM 会保障构造结束与
start()调用之间的同步语义 - 不需要手动插入
Unsafe.storeFence()或VarHandle.releaseFence()—— 这属于过度工程,反而可能干扰 JIT 优化 - 若需显式发布(如将任务放入并发队列),应使用线程安全容器(
ConcurrentLinkedQueue)或加锁,而非依赖自定义屏障
检测任务有效性应靠逻辑校验,而非内存屏障
“句柄绝对有效”本质是业务约束问题。例如任务依赖某个关闭后即失效的服务,此时应在 run() 开头主动检查:
- 用
if (service == null || service.isShutdown()) throw new IllegalStateException(...) - 若服务由外部注入,考虑使用
WeakReference或回调注册/注销机制,避免强引用导致内存泄漏 - 对资源型句柄(如文件描述符、Socket),建议在
run()中首次使用前做isOpen()类检测,而非启动前预检——因为预检到start()之间仍有竞态窗口
不复杂但容易忽略:有效性保障来自清晰的职责边界和构造时序控制,不是靠底层屏障补救设计缺陷。










