Java线程和核心数

use*_*683 22 java concurrency multithreading cpu-cores

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

我已经读过某个地方发生了线程调度,并且这种错误表明这30个线程由4个内核同时运行.这是真的,如果是这样,有人可以解释这是如何工作的,并建议一些好的阅读吗?

提前感谢您的帮助.

gar*_*ead 41

进程与线程

在过去的几天里,每个进程只有一个执行线程,因此进程被直接安排到核心上(在过去,几乎只有一个核心可以安排到).但是,在支持线程的操作系统中(几乎都是现代操作系统),它是线程,而不是计划的进程.因此,对于本讨论的其余部分,我们将专门讨论线程,您应该了解每个正在运行的进程都有一个或多个执行线程.

并行与并发

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

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

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

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

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

因此,出于我们的目的,并行性可以被认为是并发的一个特例*

调度

但是我们能够生成一个线程池(比方说30),其数量大于我们拥有的核心数量(假设为4)并让它们同时运行.如果我们只有4个核心,这怎么可能?

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

逻辑与物理核心

根据我目前的理解,核心一次只能执行1个进程

这不是真实.由于非常聪明的硬件设计和流水线操作太长而无法进入(加上我不理解),一个物理内核实际上可能同时执行两个完全不同的执行线程.如果你需要,可以稍微咀嚼那句话 - 它仍然让我大吃一惊.

这个惊人的壮举被称为同时多线程(或普遍的超线程,虽然这是这种技术的特定实例的专有名称).因此,我们有物理内核,它们是实际的硬件CPU内核和逻辑内核,这是操作系统告诉软件可以使用的内核数.逻辑核心本质上是一种抽象.在典型的现代Intel CPU中,每个物理核心充当两个逻辑核心.

有谁可以解释这是如何工作的,并建议一些良好的阅读?

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

  • 感谢您提供如此详细的解释和阅读建议. (2认同)

小智 15

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

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

一个核心一次只能执行 1 个进程

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

如果我们只有 4 个内核,这怎么可能?我还可以在我的本地计算机上运行我的 30 线程程序,并继续在我的计算机上执行其他活动

由于多任务(即并发),这是可能的。假设您启动了 30 个线程,操作系统也运行了 50 个线程,所有 80 个线程将通过一个一个获取 CPU 时间片(每次每个内核一个线程)共享 4 个 CPU 内核。这意味着平均每个内核将同时运行 80/4=20 个线程。您会感觉到所有线程/进程都在同时运行。

有人可以解释这是如何工作的吗

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

有一些像Erlang这样的语言使用绿色线程(或进程),因此它们能够在自己的消除操作系统上映射和调度线程。因此,如果您有兴趣,也可以对绿色线程进行一些研究。

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

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


And*_*ert 6

简而言之,您对核心的理解是正确的。一个核心一次可以执行 1 个线程(也称为进程)。

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

一个常见的误解:

拥有更多线程将使我的程序运行得更快。

错误:拥有更多线程并不总是能让您的程序运行得更快。这只是意味着 CPU 必须做更多的切换,实际上,由于切换所有不同进程带来的开销,线程过多会导致程序运行速度变慢