Java 并发中的 CPU 缓存一致性

更新于 2025-12-28

Jakob Jenkov 2021-07-15

在本 Java 并发教程系列的其他一些文章或视频中,你可能曾看到或听到我说过:“当一个 Java 线程写入一个 volatile 变量,或者退出一个 synchronized 块时,会将该线程可见的所有变量从 CPU 缓存刷新到主内存。”

其实这并不是真正发生的情况。

实际发生了什么?

实际情况是:所有对该线程可见、且存储在 CPU 寄存器中的变量,会被刷新到主内存(RAM)中。在写入主内存的过程中,这些变量可能会先被存入 CPU 缓存。随后,CPU / 主板会使用其缓存一致性机制,确保其他 CPU 的缓存也能看到第一个 CPU 缓存中的这些变量。

硬件甚至可能选择不将变量完全刷新到主内存,而只是保留在 CPU 缓存中——直到该 CPU 缓存需要用于存储其他数据时,才会将缓存内容写回主内存。

然而,对于运行在 CPU 上的程序代码来说,这一切都是不可见的。只要它能从指定的内存地址获取到所需的数据,那么返回的数据究竟是只存在于 CPU 缓存中,还是同时存在于主内存中,并没有区别。

你无需担心 CPU 缓存一致性是如何工作的。当然,这种缓存一致性机制会带来一点性能开销,但相比将变量全部写入主内存再从主内存加载到其他 CPU 缓存的做法,这种方式效率更高。

下图说明了上述内容。左侧的红色虚线箭头代表我在其他教程中曾错误表述的内容——即“变量从 CPU 缓存刷新到主内存”;右侧的箭头则表示实际情况——变量是从 CPU 寄存器刷新到 CPU 缓存

CPU Cache Coherence Diagram