【问题标题】:Java threads and number of coresJava 线程和内核数
【发布时间】:2016-04-13 21:12:04
【问题描述】:

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

我在某处读到过线程调度发生的情况,这给人一种错觉,即这 30 个线程由 4 个内核同时运行。这是真的吗,如果是这样,有人可以解释它是如何工作的,并推荐一些关于这个的好书吗?

提前感谢您的帮助。

【问题讨论】:

  • 哇,谢谢。所有这些都是如此出色的回应,确实有助于更好地理解这个主题。

标签: java multithreading concurrency cpu-cores


【解决方案1】:

进程与线程

在过去,每个进程只有一个执行线程,因此进程被直接调度到核心上(而在过去,几乎只有一个核心可以调度)。然而,在支持线程的操作系统(几乎所有现代操作系统)中,它是线程,而不是调度的进程。因此,在接下来的讨论中,我们将专门讨论线程,您应该了解每个正在运行的进程都有一个或多个执行线程。

并行与并发

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

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

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

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

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

因此,出于我们的目的,可以将并行性视为并发的一种特殊情况*

调度

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

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

逻辑与物理内核

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

这不是相当正确的。由于非常巧妙的硬件设计和流水线处理时间太长而无法进入这里(另外我不明白),一个物理内核可能实际上正在执行 两个完全不同的执行线程同时。如果需要,请仔细阅读这句话——它仍然让我大吃一惊。

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

有人可以解释它是如何工作的,并推荐一些关于这个的好读物吗?

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

  • parallelconcurrent 这两个术语的确切含义引起了激烈的争论,甚至 here in our very own stack overflow。这些术语的含义在很大程度上取决于应用领域。

【讨论】:

    【解决方案2】:

    Java 不执行 线程调度,它让 操作系统 来执行线程调度。

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

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

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

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

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

    谁能解释一下这是怎么回事

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

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

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

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

    【讨论】:

    • 感谢您的回复。我一定会检查 Erlang 并对绿色线程进行更多研究
    【解决方案3】:

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

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

    一个常见的误解:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      • 2015-04-08
      • 1970-01-01
      • 1970-01-01
      • 2014-02-07
      相关资源
      最近更新 更多