final关键字通过jmm的重排序限制和可见性保证实现安全发布:final字段写入不被重排到构造函数外,首次读引用必见其正确初始值,但仅限final字段且需对象正确构造。

final 关键字在多线程中保障“安全发布”,核心不是靠加锁或同步,而是通过 JVM 内存模型(JMM)施加的编译器重排序限制和运行时可见性保证来实现的。
final 域的写入不被重排序到构造函数外
当一个对象的 final 字段在构造函数中被赋值,JVM 会插入内存屏障(如 StoreStore),确保:
- 该 final 字段的写操作不会被编译器或处理器重排到构造函数结束之后;
- 构造函数内对其他普通字段的写入,也不会被重排到 final 字段写入之前(但可能在其后)。
首次读取对象引用时,final 域值必然已初始化
只要一个线程是通过合法方式(如直接持有 new 出来的引用)首次读取到该对象的引用,那么它一定能看到所有 final 字段的正确初始值——即使没有 synchronized 或 volatile 修饰。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 这个保证仅适用于 final 字段本身,不延伸至非 final 字段;
- 前提是对象本身是“正确构造”的(即构造函数执行完毕才让引用逸出);
- 如果构造过程中 this 引用逃逸(如在构造器里启动线程或注册监听器),该保证失效。
与普通变量的根本区别:绕过“部分初始化”风险
普通对象发布存在三步非原子问题:分配内存 → 设置引用 → 初始化字段。若第二步完成后就被其他线程读到,可能看到未初始化的字段值。
- final 字段打破了这种不确定性:JVM 规定,一旦 final 字段完成写入,就视为对象“逻辑上可用了”;
- 配合“正确构造”,final 让“对象发布”和“字段可见”形成天然绑定,无需额外同步即可避免读到默认值(如 0、null)。
注意边界:它不等于线程安全,也不替代整体同步
final 只解决 final 字段自身的安全发布问题:
- 对象中非 final 字段仍可能不可见或不一致;
- 对象内容本身可变(如 final List
list = new ArrayList(); list.add(...) 是允许的); - 多个线程并发修改同一对象的非 final 状态,仍需 synchronized、volatile 或并发工具类保障。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南









