单核cpu不存在可见性问题,因其所有线程共用同一缓存,修改后立即对其他线程可见;多核cpu因各核心拥有独立l1缓存,线程间变量修改不自动同步,导致可见性失效。

单核 CPU 上基本不存在可见性问题,多核 CPU 上则普遍存在——根本差异在于缓存结构是否隔离。
单核 CPU:共享缓存,天然可见
所有线程都在同一个 CPU 核心上调度,共用同一级缓存(如 L1/L2)。一个线程写入变量后,该值会留在共享缓存中,其他线程紧接着读取时,直接命中缓存,拿到的就是最新值。
- 不需要额外同步机制,普通变量读写即可满足多数场景的可见要求
- 即使有编译器或 JVM 优化,也不会因缓存隔离导致“看不到更新”
- 问题焦点通常落在原子性或有序性上,而非可见性
多核 CPU:私有缓存,可见性失效常见
每个核心拥有独立的 L1 缓存,L2/L3 缓存可能共享也可能分片。线程 A 在 Core1 修改变量,写入的是 Core1 的 L1 缓存;线程 B 在 Core2 读取同一变量,若未刷新或同步,仍从自己的 L1 缓存读旧值——这就是典型的可见性丢失。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 变量修改后不立即对其他核心上的线程可见,尤其在无同步手段时
- JIT 编译器还可能将变量缓存在寄存器或线程本地工作内存中,进一步加剧不可见
- 典型表现:循环标志位(如 while (running))无法及时退出
解决思路依赖硬件与语言协同
可见性不是纯软件问题,而是软硬协同的结果:
- CPU 层通过缓存一致性协议(如 MESI)保证缓存行状态同步,但不保证写操作何时被其他核感知
- JMM 抽象出“主内存”和“工作内存”,用 volatile、synchronized 或 final 触发内存屏障,强制刷新缓存、禁止重排序
- volatile 写操作会触发 StoreStore 和 StoreLoad 屏障,确保之前所有写对其他线程可见;volatile 读则插入 LoadLoad 和 LoadStore,保证后续读能看到最新值
实际影响比理论更直接
现代开发几乎全部运行在多核环境,单核只是历史背景。JMM 的设计初衷就是为多核场景建模——所以即使代码在单核机器上测试通过,换到多核服务器仍可能出错。可见性问题不是“会不会发生”,而是“什么时候暴露”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










