Java 线程和内核数

Java threads and number of cores

我刚刚有一个关于处理器和线程如何工作的快速问题。按照我目前的理解,一个core一次只能执行1个进程。但是我们能够生成一个线程池(假设 30 个),其数量大于我们拥有的内核数(假设 4 个),并同时让它们 运行。如果我们只有 4 个核心,这怎么可能?我还可以 运行 在我的本地计算机上运行我的 30 线程程序,还可以继续在我的计算机上执行其他活动,例如看电影或浏览互联网。

我在某处读到线程调度发生,这给人一种错觉,即这 30 个线程正在 运行4 个内核并发运行。这是真的吗?如果是的话,有人可以解释它是如何工作的,并推荐一些好的读物吗?

提前感谢您的帮助。

进程与线程

在过去,每个进程恰好有一个线程执行,所以进程直接调度到核心上(而在过去,几乎只有一个核心可以执行安排上)。但是,在支持线程的操作系统中(几乎所有现代 OS 的操作系统),它是 线程 ,而不是被调度的进程。因此,在本次讨论的其余部分,我们将专门讨论线程,您应该了解每个 运行ning 进程都有一个或多个执行线程。

并行与并发

当两个线程运行并并联时,它们同时运行并.例如,如果我们有两个线程 A 和 B,那么它们的并行执行将如下所示:

CPU 1: 一个------------------------>

CPU 2: B -------------------------->

当两个线程运行并发时,它们的执行重叠。重叠可以通过以下两种方式之一发生:线程同时执行(即并行,如上所述),或者它们的执行在处理器上交错,如下所示:

CPU 1: A ----------> B ----------> A ----------> B ---------->

所以,为了我们的目的,并行性可以被认为是并发的特例*

计划

But we are able to produce a thread pool(lets say 30) with a larger number than the number of cores that we posses(lets say 4) and have them run concurrently. How is this possible if we are only have 4 cores?

在这种情况下,它们可以 运行 并发,因为 CPU 调度程序为这 30 个线程中的每个线程分配了一些 CPU 时间。有些线程 并行 运行(如果你有 4 个核心,那么 4 个线程将 运行 并行在任何时候),但所有30 个线程将同时 运行ning。然后你可以去玩游戏或浏览网页的原因是这些新线程被添加到线程 pool/queue 并且还分享了 CPU 时间。

逻辑内核与物理内核

According to my current understanding, a core can only perform 1 process at a time

不完全。由于非常聪明的硬件设计和流水线太长了无法进入这里(加上我不明白),一个物理核心可能实际上正在执行两个完全不同的执行线程同时。如果需要,请仔细阅读这句话——它仍然让我印象深刻。

这项惊人的壮举被称为同步 multi-threading(或流行的 Hyper-Threading,尽管这是此类技术特定实例的专有名称)。因此,我们有 物理核心,这是实际的硬件 CPU 核心,以及 逻辑核心,这是核心的数量操作系统告诉软件可以使用。逻辑核心本质上是一种抽象。在典型的现代英特尔 CPU 中,每个物理核心充当两个逻辑核心。

can someone explain how this works and also recommend some good reading on this?

如果您真的想了解进程、线程和调度如何协同工作,我会推荐操作系统概念

  • 术语 并行并发 的确切含义备受争议,甚至 here in our very own stack overflow。这些术语的含义在很大程度上取决于应用领域。

总之,你对一个内核的理解是正确的。一个核心一次可以执行 1 个线程(又名进程)。

但是,您的程序并不真的 运行 一次有 30 个线程。在这 30 个线程中,一次只有 4 个 运行ning,其他 26 个在等待。 CPU 将调度线程并为每个线程分配时间片以 运行 在一个核心上。所以CPU会让所有线程轮流运行ning.

一个常见的误解:

Having more threads will make my program run faster.

FALSE:拥有更多线程不会总是让您的程序运行更快。这只是意味着 CPU 必须做更多的切换,事实上,线程太多会使你的程序 运行 变慢 因为切换造成的开销列出所有不同的进程。

Java不执行线程调度,它留给操作系统执行线程调度。

对于计算密集型 任务,建议线程池大小等于可用内核数。但是对于 I/O 绑定 任务,我们应该有更多的线程。如果两种类型的任务都可用并且需要 CPU 时间片,还有许多其他变体。

a core can only perform 1 process at a time

是的,但他们可以多任务处理并制造一种错觉他们一次处理多个进程

How is this possible if we are only have 4 cores? I am also able to run my 30 thread program on my local computer and also continue to perform other activities on my computer

这是可能的,因为 多任务处理 (即 并发性)。假设您启动了 30 个线程,并且 OS 也是 运行 宁 50 个线程,所有 80 个线程将通过逐个获取 CPU 时间片共享 4 CPU 个内核(一个线程一次每个核心)。这意味着平均每个核心将 运行 80/4=20 个线程并发。而且你会感觉到所有 threads/processes 同时 运行ning。

can someone explain how this works

所有这一切都发生在OS级别。如果你是一名程序员,那么你不应该担心这个。但是,如果您是 OS 的学生,那么选择任何 OS 书籍并在 OS 级别详细了解 Multi-threading 或找到一些好的研究论文以进行深入研究。你应该知道的一件事是每个 OS 以不同的方式处理这些事情(但通常概念是相同的)

有些语言,如 Erlang,使用绿色线程(或进程),因此它们能够自行映射和调度线程,从而消除了 OS.因此,如果您有兴趣,也可以研究一下 green threads

注意: 您还可以研究 actors,这是线程上的另一个 abstraction。 Erlang、Scala 等语言使用参与者来完成任务。一个线程可以有一百个演员;每个参与者可以执行不同的任务(类似于 java 中的线程)。

这是一个非常广泛而活跃的研究课题,有很多东西要学。