首页 > 解决方案 > Java内存模型:单线程多核CPU

问题描述

在 Java 应用程序中,如果对对象状态的访问发生在同一个线程上(在最简单的情况下,在单线程应用程序中),则无需根据发生前关系规范进行同步以强制更改的可见性/一致性:

“两个动作可以通过happens-before关系排序。如果一个动作发生在另一个动作之前,那么第一个动作对第二个动作可见并在第二个之前排序。

如果我们有两个动作 x 和 y,我们写 hb(x, y) 来表示 x 发生在 y 之前。

如果 x 和 y 是同一线程的操作,并且 x 在程序顺序中位于 y 之前,则 hb(x, y)。"

但是现代架构是多核的,因此 Java 线程可以在任何给定时间在其中任何一个上执行(除非这不是真的并且 Java 线程被固定到特定的内核?)。因此,如果是这种情况,如果一个线程写入变量 x,将其缓存在 L1 缓存或 CPU 寄存器中,然后开始在另一个内核上运行,该内核先前访问过 x 并将其缓存在寄存器中,那么该值是不一致的。 . 当线程从 CPU 中取出时,是否有某种机制(隐式内存屏障)?

标签: javaconcurrencysynchronizationmemory-barriersmemory-model

解决方案


可以在任何给定时间对其中任何一个执行

任务不只是自发地在核心之间迁移。这些事情必须发生:

  • 该任务在之前运行的内核上被抢占(在内核的全局任务列表中将其标记为等待运行)
  • 另一个内核上的内核任务调度程序看到该任务正在等待 CPU 并决定运行它。

(调度是一种分布式算法;每个内核都在该内核上有效地运行内核,非常像一个多线程进程。一个内核无法告诉另一个内核该做什么,只能将数据放在内核在该内核上运行的内存中可以看看。)


这不是问题,因为:

数据缓存(L1 等)在操作系统可以调度线程的所有内核上是一致的。 程序员相信 CPU 缓存的神话

或者在假设且不太可能的硬件 + 操作系统 + JVM 上运行线程跨内核具有非连贯共享内存,操作系统将不得不在停止一个内核上的任务后的某个时间点将脏私有缓存刷新回实际共享内存,然后再将其在全局任务队列中,另一个内核上的任务调度程序可以运行它。

从 CPU 中取出线程时是否存在某种机制(隐式内存屏障)?

在真实世界的系统(相干缓存)上,操作系统只需要确保有一个完整的内存屏障会在另一个内核恢复任务之前耗尽一个内核上的存储缓冲区。

无论如何,这个障碍并不总是隐含的操作系统要做的事情的一部分。操作系统内核可能需要为此明确包含一个屏障。但是,保存寄存器状态并将任务标记为可运行可能至少需要释放存储,因此可以恢复此任务状态的另一个核心也将看到该任务已完成的所有用户空间存储。

不过,我听说过在没有足够障碍的情况下在 CPU 之间迁移来破坏单线程进程的可能性。对于 OS 来说,这是需要考虑的事情。它根本不是 Java 特定的。它是关于如何不破坏运行任意机器代码的单个线程。


只有寄存器是真正私有的,是的,编译器会将变量保存在寄存器中。我不喜欢“缓存”这个词。在 asm 中,寄存器与内存是分开的。编译器可以在循环期间将变量的唯一当前有效副本保留在寄存器中,然后将其存储回来。

每个任务都有自己的寄存器状态;这称为“架构状态”,是由上下文切换保存/恢复的上下文。

在另一个内核上重新开始执行线程意味着从内存中恢复其保存的寄存器状态,以恢复其程序计数器结束。即跳转到它停止的指令,将程序计数器恢复到体系结构程序计数器寄存器中。例如 x86-64 上的 RIP。(“指令指针”寄存器的 64 位版本)

请注意,寄存器和(虚拟)内存内容是用户空间进程(以及打开的文件描述符和与之相关的其他内核内容)的整个状态。但缓存状态不是。寄存器不是缓存。缓存对软件是透明的(内存重新排序是因为存储缓冲区和 CPU 内存并行性来隐藏缓存未命中,而不是因为缓存,在大多数 ISA 上)。寄存器是局部变量的 asm 等价物。


编译器术语:“缓存”

将负载提升出循环并将值保存在寄存器中有时被描述为“缓存”寄存器中的值,但这只是让您在这里感到困惑的偶然术语。编译器开发人员的术语是变量的“注册”。

或者只是从循环中“提升”负载或“下沉”商店;通常,您需要先将一个值加载到寄存器中,然后才能将其用于其他用途(至少在没有内存源 ALU 指令的 RISC 上)。通过提升循环不变值的负载,您只需在循环之前加载一次,然后多次重新读取寄存器。

商店也一样;如果您知道不允许其他线程查看变量的内存位置,则只有最终值需要使用存储指令实际存储。如果没有任何东西可以读取它们,那么任何其他值的存储将是“死的”,并且我们知道有一个稍后的存储。因此,您在循环期间将变量保存在寄存器中,然后在最后存储一次。这被称为“下沉”商店,并且与死店消除有关。


推荐阅读