讲师中心 微信公众号
AI工具推荐 视频效率加速

Java多线程怎么保证可见性 Java内存模型JMM原理分析【源码】

大磊姑娘_5650

大磊姑娘_5650

发布时间:2026-03-20 08:53:56

|

349人浏览过

|

来源于php中文网

原创

volatile 解决多线程下变量修改不被立即可见的问题,通过强制主内存读写和插入内存屏障禁止重排序,但不保证复合操作原子性。

java多线程怎么保证可见性 java内存模型jmm原理分析【源码】

volatile 关键字到底解决了什么问题

Java 多线程中变量修改不被其他线程立即看到,根本原因不是“线程没刷新”,而是 JMM 允许每个线程拥有自己的工作内存(缓存),对 sharedVar 的读写可能只发生在本地副本上。用 volatile 修饰后,每次读都强制从主内存加载,每次写都立即刷回主内存,并插入内存屏障禁止重排序。

常见错误现象:while (!flag) { Thread.sleep(100); } 中 flag 被另一个线程设为 true,但当前线程永远不退出——因为 flag 没加 volatile,JIT 可能将其优化为常量判断或缓存到寄存器。

  • volatile 不能替代锁:它不保证复合操作的原子性(如 i++)
  • 适用于“一写多读”且无依赖关系的场景,比如状态标志、单次发布的对象引用
  • 在 JDK 1.5+ 后语义已严格基于 JMM 定义,旧版(如 1.4)行为不可靠

synchronized 和 final 怎么参与可见性保障

synchronized 块的进入和退出分别具有“读屏障”和“写屏障”效果:进入时清空本地工作内存,强制从主内存重新读取共享变量;退出时将本线程所有修改刷回主内存。这比 volatile 更重,但能同时解决原子性和可见性。

final 字段的可见性是编译期+运行期协同保证的:构造器内对 final 字段的写入,在构造完成前就对其他线程可见(前提是该对象未在构造过程中逸出)。这是通过禁止编译器/JIT 将 final 写操作重排序到构造器末尾之后实现的。

立即学习“Java免费学习笔记(深入)”;

  • 不要在构造器里把 this 引用发布出去(如注册监听器、启动线程),否则 final 字段可能被看到默认值
  • synchronized(this) 和 synchronized(staticObj) 的可见性作用域不同:前者只同步实例变量,后者才影响静态变量
  • JDK 9+ 中 VarHandle 的 setRelease/getAcquire 提供了更细粒度的控制,语义接近 volatile 但可指定内存序

为什么 AtomicXXX 类能保证可见性却不显式用 volatile

以 AtomicInteger 为例,其内部 value 字段声明为 volatile:

private volatile int value;
所有原子方法(如 incrementAndGet())底层调用的是 Unsafe.compareAndSwapInt(),该指令本身具有内存屏障语义,且会触发 JVM 对 volatile 字段的读写协议。

容易忽略的点:AtomicInteger.get() 等读方法之所以可见,不是因为 CAS,而是因为字段本身是 volatile;而 lazySet()(即 setRelease)则只保证写入不重排序到之后,但不强制立即刷回主内存,适合性能敏感的“单向通知”场景。

  • 不要误以为 AtomicXXX 的所有方法都等价于加锁——weakCompareAndSet 在某些平台可能失败而不抛异常,也不提供强顺序保证
  • 若需对多个变量做原子更新,AtomicReferenceFieldUpdater 或 VarHandle 比锁更轻量,但要求字段必须是 volatile

JMM 源码里哪几行真正定义了 happens-before 规则

JMM 并没有一行“源码”直接定义 happens-before,它是规范层面的抽象模型。但在 OpenJDK 实现中,关键逻辑体现在:hotspot/src/share/vm/opto/graphKit.cpp 中的内存屏障插入策略、hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp 中对 membar 指令的生成、以及 hotspot/src/share/vm/runtime/synchronizer.cpp 中 monitor enter/exit 的内存语义处理。

真正影响开发者的是 Java 语言规范(JLS)第 17.4 节规定的 7 条 happens-before 规则,它们被编译器和 JVM 实现为具体屏障指令。比如“监视器锁规则”对应 synchronized 块退出时插入 StoreLoad 屏障,“volatile 变量规则”对应每次 volatile 写后插入 StoreStore + StoreLoad。

  • happens-before 是偏序关系,不是时间先后——A happens-before B,不代表 A 一定在 B 之前执行,只代表 A 的结果对 B 可见
  • JIT 编译器在满足 happens-before 前提下,仍可自由重排序指令,这是性能优化的基础,也是理解“看似乱序却不出错”的关键
  • 调试时用 -XX:+PrintAssembly 查看汇编,能看到 lock addl $0x0,(%rsp) 这类隐式内存屏障,就是 JVM 插入的
JMM 的复杂性不在语法,而在它把硬件内存模型、编译器优化、JVM 实现细节全揉进一套程序员可感知的语义里。最常被绕过的坑,是以为加了 volatile 就万事大吉,却忘了它不阻止指令重排对非 volatile 字段的影响。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

5824

2023.10.24

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

334

2023.09.25

c++中volatile关键字的作用
c++中volatile关键字的作用

本专题整合了c++中volatile关键字的相关内容,阅读专题下面的文章了解更多详细内容。

674

2025.10.23

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

3598

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

1029

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

363

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

519

2026.01.21

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

349

2026.02.06

Buffalo框架数据库开发全教程
Buffalo框架数据库开发全教程

本专题围绕Buffalo框架数据库开发,讲解database.yml多环境配置、soda与fizz迁移生成回滚、模型结构体标签、增删改查与条件查询、一对多与多对多关联、数据校验、回调钩子、事务处理及原生SQL执行能力。

180

2026.09.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn