【发布时间】:2016-12-30 10:33:01
【问题描述】:
有人可以帮助我了解 JVM 如何在可用的 CPU 内核之间传播线程吗?这是我的愿景,但请纠正我。
所以从一开始:当计算机启动时,引导线程(通常是处理器 0 中核心 0 中的线程 0)开始从地址 0xfffffff0 获取代码。其余所有 CPU/内核都处于称为 Wait-for-SIPI(WFS) 的特殊睡眠状态。
然后在加载操作系统后,它开始管理进程并在 CPU/内核之间调度它们,通过称为 SIPI(启动 IPI)的高级可编程中断控制器 (APIC) 向每个线程发送一个特殊的处理器间中断 (IPI)在 WFS 中。 SIPI 包含该线程应开始获取代码的地址。
例如,操作系统通过在内存中加载 JVM 代码并将 CPU 内核之一指向其地址来启动 JVM(使用上述机制)。之后,作为具有自己的虚拟内存区域的单独 OS 进程执行的 JVM 可以启动多个线程。
所以问题是:如何?
JVM 是否使用与 OS 相同的机制,并且在 OS 给 JVM 的时间片内,是否可以将 SIPI 发送到其他内核并指向应该在单独线程中执行的任务的地址?如果是,那么如何恢复该内核上操作系统可以执行的原始程序?
假设这是不正确的愿景,因为假设涉及其他 CPU/内核的任务应该通过操作系统进行管理。否则,我们可能会中断一些在其他内核上并行运行的操作系统进程的执行。因此,如果 JVM 想要在其他 CPU/内核上启动新线程,它会进行一些操作系统调用并将要执行的任务的地址发送到操作系统。操作系统与其他程序一样调度执行,但不同的是,此执行应该发生在同一个进程中,以便能够访问与其余 JVM 线程相同的地址空间。
它是如何完成的?有人可以详细描述一下吗?
【问题讨论】:
-
JVM是一个普通的进程。它(及其线程)由操作系统/内核管理,包括创建和调度。就像所有其他进程和线程一样。加粗的部分也没有什么特别之处——所有常用线程都是这样工作的。
-
我们可以从 JVM 中操作哪个 CPU 和内核应该用于某个线程还是完全在操作系统控制之下?
-
这是特定于平台的。如果您可以编写本机代码,那么在 Linux 中手动调度是通过
sched_setaffinity系统调用完成的。据我所知,标准库中没有 java 包装器。还可以查看taskset命令以运行修改后的关联性的整个 JVM。
标签: java multithreading jvm cpu-cores