技术演进中的开发沉思-354:java内存模型(下)
今天就内存模型作最后的梳理Java 共享内存模型下线程通信的唯一标准底层流程也是之前所有 JMM 核心抽象的实际落地—— 共享内存模型的 “隐式通信”本质就是通过「线程本地内存与主内存的共享变量同步」完成的这两步流程是多线程通过共享变量交换信息的唯一间接路径所有基于共享变量的线程协作最终都要遵循这个底层逻辑。这个流程的核心是 **「刷新 - 读取」的双向同步 **而同步机制volatile/synchronized/ 原子类的唯一作用就是强制保证这两步流程的「及时、可靠执行」如果没有同步机制约束这两步会因 JMM 的默认 “同步延迟” 执行不及时导致线程通信失败也就是之前讲的可见性问题。下面结合你的核心流程补充每一步的执行细节、同步机制的约束作用、代码示例验证、与消息传递模型的对比让你直观理解 “流程如何工作”“为何会通信失败”“同步机制如何修复”。一、共享内存模型首先明确一个关键前提共享内存模型中线程间没有任何直接通信的方式线程 A 无法直接访问线程 B 的本地内存所有通信都必须以主内存为中介通过「本地内存→主内存→本地内存」的间接路径完成而你梳理的两步就是这个间接路径的标准化拆解。这个流程的设计初衷是兼容 CPU 硬件的缓存特性利用本地内存 / 缓存提升线程操作效率但也因此引入了 “同步延迟” 的问题 ——JMM 默认不会强制线程立即执行这两步而是由 JVM/CPU 按需调度这是可见性问题的直接根源。二、线程通信两步流程结合 JMM 的主内存 / 本地内存抽象对每一步的执行主体、操作内容、默认行为、同步约束做精准拆解核心关注 **「默认行为」和「同步约束」的差异 **这是通信成败的关键。1、线程 A 将本地内存中更新的共享变量刷新到主内存执行主体修改变量的写线程线程 A操作内容线程 A 将自己本地内存中修改后的共享变量副本同步回主内存覆盖主内存中该变量的旧值让主内存保持「最新值」JMM 默认行为不立即执行—— 写操作会先存在 CPU 写缓冲区再批量、延迟刷入主内存提升执行效率线程 A 执行完变量新值后可能很久都不执行这一步同步机制的强制约束加了volatile/synchronized后会立即强制执行这一步volatile写操作后立即强制刷新无延迟synchronized线程释放锁时退出同步代码块立即强制刷新所有在临界区修改的共享变量。2、线程 B 从主内存读取线程 A 更新后的共享变量到本地内存执行主体读取变量的读线程线程 B操作内容线程 B 放弃自己本地内存中该共享变量的旧副本从主内存重新拷贝最新值到自己的本地内存生成新副本后续操作基于新副本执行JMM 默认行为不立即执行—— 线程 B 会优先读取自己本地内存的旧副本缓存命中不会主动去主内存刷新即使主内存已经有了新值同步机制的强制约束加了volatile/synchronized后会立即强制执行这一步volatile读操作前立即强制从主内存刷新放弃旧副本synchronized线程获取锁时进入同步代码块立即强制从主内存刷新所有共享变量的最新值。流程本质线程 A 的 “写通信” 是本地→主存的单向同步线程 B 的 “读通信” 是主存→本地的单向同步两者结合就是完整的线程通信缺一步则通信失败。三、验证流程用最经典的线程停止标记示例直观演示「无同步时流程延迟导致通信失败」以及「加 volatile 后强制流程及时执行实现通信成功」让你看到流程和同步机制的直接关联。无同步机制 —— 流程执行延迟线程通信失败可见性问题public class CommunicationFail { // 共享变量主内存初始值false无任何同步约束 private static boolean stopFlag false; public static void main(String[] args) throws InterruptedException { // 线程B读线程循环读取stopFlag期望收到停止信号 new Thread(() - { System.out.println(线程B开始运行等待停止信号...); // 【步骤2未强制执行】线程B一直读取自己本地内存的旧副本false从不主动刷新主内存 while (!stopFlag) { // 空循环无任何操作 } System.out.println(线程B收到停止信号停止运行); }, 线程B).start(); // 主线程休眠1秒让线程B先启动并进入循环 Thread.sleep(1000); // 线程A主线程写线程修改stopFlag为true stopFlag true; System.out.println(线程A已发送停止信号stopFlagtrue); // 结果线程B会无限循环永远收不到停止信号通信失败 } }失败根源线程 A主线程修改stopFlagtrue后JMM 默认未立即执行步骤 1刷新到主内存修改仅停留在主线程的本地内存线程 B一直默认执行旧逻辑步骤 2 未强制执行反复读取自己本地内存中stopFlagfalse的旧副本从不主动去主内存刷新两步流程都因 “同步延迟” 未执行最终导致线程 A 的信号无法传递给线程 B通信失败。加 volatile 同步 —— 强制流程及时执行线程通信成功仅需给共享变量加volatile关键字就能强制约束两步流程立即、可靠执行实现通信成功public class CommunicationSuccess { // 加volatile强制约束步骤1和步骤2的及时执行 private static volatile boolean stopFlag false; public static void main(String[] args) throws InterruptedException { new Thread(() - { System.out.println(线程B开始运行等待停止信号...); while (!stopFlag) { // 空循环 } System.out.println(线程B收到停止信号停止运行); }, 线程B).start(); Thread.sleep(1000); // 线程A修改volatile强制执行【步骤1】立即刷新到主内存 stopFlag true; System.out.println(线程A已发送停止信号stopFlagtrue); // 结果线程B立即收到信号退出循环通信成功 } }成功核心volatile对共享变量的双向强制约束对写线程 A修改stopFlagtrue后立即强制执行步骤 1将新值从本地内存刷新到主内存主内存瞬间更新为最新值对读线程 B每次判断!stopFlag时立即强制执行步骤 2放弃本地内存的旧副本从主内存读取最新值两步流程被强制 “即时执行”线程 A 的信号通过主内存顺利传递给线程 B通信完成。synchronized 的约束逻辑基于锁的释放 / 获取synchronized同样能保证这个流程的可靠执行只是约束方式是基于锁的「释放 - 获取」成对操作比 volatile 的粒度更粗同时保证原子性、有序性private static boolean stopFlag false; private static final Object lock new Object(); // 线程A写线程释放锁时强制执行步骤1 synchronized (lock) { stopFlag true; // 修改变量 } // 释放锁强制将stopFlag的新值刷新到主内存步骤1 // 线程B读线程获取锁时强制执行步骤2 while (true) { synchronized (lock) { // 获取锁强制从主内存读取stopFlag的最新值步骤2 if (stopFlag) { break; } } }核心逻辑线程释放锁时JMM 会强制将该线程本地内存中所有修改的共享变量刷新到主内存步骤 1线程获取锁时JMM 会强制将该线程本地内存的共享变量副本失效必须从主内存重新读取步骤 2。四、两步流程需要注意的是你梳理的 **“步骤 1→步骤 2” 是一个连续的通信逻辑但并非原子操作 **—— 两步之间可能存在其他线程的介入这也是为什么复合操作需要保证原子性比如多个线程同时修改一个共享变量count线程 A 执行步骤 1 刷新count1后线程 C 可能立即执行步骤 1 刷新count2线程 B 此时执行步骤 2读取到的会是线程 C 的最新值而非线程 A 的。这种情况并非通信失败而是多线程竞争下的正常结果同步机制的作用是保证 “读取的一定是主内存的最新值”而原子类AtomicXxx的作用是保证 “修改变量 刷新主内存” 的步骤 1 是原子操作避免多线程修改时的数值覆盖。五、与消息传递模型的通信流程对比强化理解为了更清晰的区分两大通信模型的核心差异把共享内存模型的这个底层流程和消息传递模型的通信流程做对比能更直观看到 “隐式通信” 和 “显式通信” 的本质区别通信模型核心通信流程通信媒介同步约束方式核心特点共享内存模型线程 A本地→主存步骤 1线程 B主存→本地步骤 2堆内存的共享变量同步机制强制流程即时执行隐式通信、间接主存为中介消息传递模型线程 A显式发送消息入队线程 B显式接收消息出队阻塞队列 / 消息队列框架内置阻塞机制满 / 空阻塞显式通信、直接队列做媒介核心差异共享内存模型的通信是隐式的—— 线程无需知道 “谁在和我通信”只需读写共享变量JMM 自动完成底层的刷新 / 读取消息传递模型的通信是显式的—— 线程必须通过put()/take()等 API 显式发送 / 接收消息通信行为完全由开发者控制。最后小结你梳理的「刷新主存→读取主存」两步是共享内存模型下线程通信的唯一底层流程所有基于共享变量的隐式通信都遵循这个逻辑主内存是唯一的通信中介流程的核心是共享变量的「双向同步」线程间无直接通信能力只能通过本地内存与主内存的同步完成信息交换同步机制volatile/synchronized/ 原子类的核心作用是强制保证这两步流程的及时、可靠执行消除 JMM 默认的 “同步延迟”解决可见性问题无同步机制时流程会因延迟执行导致通信失败线程间无法感知彼此的修改加同步机制后流程被强制即时执行实现通信成功两步流程是逻辑连续的但非原子操作多线程竞争下可能有其他线程介入复合操作需额外保证原子性该流程是共享内存模型独有的与消息传递模型的 “显式发送 - 接收” 形成本质区别也是 Java 并发问题的核心来源。

相关新闻

Java基础

Java基础

面对对象Static成员方法分类man方法设计模式单例设计模式继承

2026/7/3 6:30:00 阅读更多 →
Multiplatform - 使用 Jetpack 组件(ViewModel、Navigation3)

Multiplatform - 使用 Jetpack 组件(ViewModel、Navigation3)

一、概念二、ViewModel2.1 添加依赖[versions] viewModel "2.9.6"[libraries] jetbrains-viewModel { module "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref "viewModel" } //可选(解决桌面端对…

2026/7/3 14:27:01 阅读更多 →
静态 IP 是什么?静态IP的应用场景有哪些?

静态 IP 是什么?静态IP的应用场景有哪些?

1 静态 IP 是什么 “静态 IP”指在约定租期内长期保持不变的公网出口地址。与“动态 IP”着重“会变”不同,静态 IP 的核心价值是恒定性。这种恒定性让上游系统可以:以IP 白名单方式快速对接第三方 API;在长连接/长登录态下稳定持续传输&…

2026/7/4 23:51:25 阅读更多 →

最新新闻

【Hermes入门11讲】第四讲:给Hermes装上手脚——工具与工具集

【Hermes入门11讲】第四讲:给Hermes装上手脚——工具与工具集

工具是Hermes和普通AI聊天最大的区别。没有工具,它只能嘴上说;有了工具,它真能动手干。 工具是什么 简单说,工具就是Hermes能执行的具体动作。比如: • 搜索网页 • 执行终端命令 • 读写文件 • 操作浏览器 • 生…

2026/7/5 4:57:22 阅读更多 →
如何用嘎嘎降AI处理英语专业论文:英语专业毕业论文降AI知网4.8元完整操作教程

如何用嘎嘎降AI处理英语专业论文:英语专业毕业论文降AI知网4.8元完整操作教程

如何用嘎嘎降AI处理英语专业论文:英语专业毕业论文降AI知网4.8元完整操作教程 处理英语专业论文降AI教程时最怕两件事:降不下来,和改完不知道对不对。 这篇把整个流程梳理清楚,用嘎嘎降AI(www.aigcleaner.com&#x…

2026/7/5 4:51:21 阅读更多 →
为庆祝《终结者 2》上映 35 周年,工业光魔创始人探讨 T-1000 特效技术挑战

为庆祝《终结者 2》上映 35 周年,工业光魔创始人探讨 T-1000 特效技术挑战

【导语:为庆祝《终结者 2》上映 35 周年,工业光魔计算机图形部门几位创始人聚在一起,探讨打造液态金属 T - 1000 角色面临的技术挑战,想了解电影特效可看迪士尼纪录片。】《终结者 2》35 周年:特效技术探讨重聚在《终结…

2026/7/5 4:51:21 阅读更多 →
GESP2026年6月认证C++二级( 第一部分选择题(1-7))精讲

GESP2026年6月认证C++二级( 第一部分选择题(1-7))精讲

第一题 未来农场的神奇传感器(答案:C)1、📖故事开始(1)今天,小明来到了未来智慧农场。农场里没有农民拿着水壶浇地,而是有一个小机器人不停地说:"土地有点干了&…

2026/7/5 4:49:20 阅读更多 →
Sketch批量重命名插件终极指南:告别手动命名,提升设计效率10倍

Sketch批量重命名插件终极指南:告别手动命名,提升设计效率10倍

Sketch批量重命名插件终极指南:告别手动命名,提升设计效率10倍 【免费下载链接】RenameIt Keep your Sketch files organized, batch rename layers and artboards. 项目地址: https://gitcode.com/gh_mirrors/re/RenameIt 你是否曾因Sketch文件中…

2026/7/5 4:49:20 阅读更多 →
图像频域滤波实战:3步实现基于2D-FFT的高斯低通与高通滤波

图像频域滤波实战:3步实现基于2D-FFT的高斯低通与高通滤波

图像频域滤波实战:3步实现基于2D-FFT的高斯低通与高通滤波 1. 频域滤波的核心原理 当你第一次看到图像的频域表示时,可能会觉得那些对称的亮斑和条纹像某种抽象艺术。但正是这些看似神秘的图案,蕴含着图像处理的强大力量。频域滤波的核心思想…

2026/7/5 4:45:18 阅读更多 →

日新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻