【问题标题】:Is multithreading actually parallel processing or just an illusion of one?多线程实际上是并行处理还是只是一种错觉?
【发布时间】:2018-04-11 06:33:09
【问题描述】:

假设有 10 个不相交且独立的任务。如果单线程执行需要 10 分钟,每个任务需要 1 分钟,那么 10 个线程,每个任务一个线程会在 1 分钟内完成执行吗?

因为一次只能运行一条指令并且假设 CPU 只运行这个进程。 多线程不只是线程之间非常快速的上下文切换,给人一种并行处理的错觉,但实际上并不是在处理吗?

那么,既然CPU要执行的指令数是一样的,那么不管是单线程还是多线程,完成的时间不应该是一样的吗? 如果是,那不是说多线程是一种并行处理的手段是错误的吗?

【问题讨论】:

  • 您似乎假设您正在执行程序的计算机只有一个 CPU 内核。对于当今活跃使用的大多数计算机而言,这不太可能是真的。对于多核 CPU 或多 CPU 系统,多线程可以实现实际的并行处理。
  • “因为一次只能运行一条指令”你在哪里找到的?
  • 使用多线程并不意味着你会看到速度提升。
  • Ummm ... 使用多线程并不一定意味着您会看到速度提升。

标签: java multithreading


【解决方案1】:

Java 多线程通常提供真正的并行性......而不仅仅是并行性的幻觉。

假设有 10 个不相交且独立的任务。如果单线程执行需要 10 分钟,每个任务需要 1 分钟,那么 10 个线程,每个任务一个线程在 1 分钟内完成执行吗?

可能是,可能不是。这取决于几件事:

  1. 任务真的是不相交的吗?例如,如果它们涉及共享数据结构和同步,它们就不是不相交的。

  2. 是否有(至少)10 个物理内核可用于运行 10 个线程?

  3. 它们的 10 个线程的足够内存带宽对我来说不是瓶颈读取/写入 RAM 吗?

因为一次只能运行一条指令...

实际上,这在技术上是不正确的。即使是单核,由于流水线,一个 CPU 也可以同时执行多条指令。

但我们可以说,传统机器上的给定内核或超线程通常一次只执行一个指令流。

...假设 CPU 只运行这个进程。

我假设您指的不是 GPU1,也不是只有一个内核且没有超线程的 CPU。

即使对于如今的低端笔记本电脑/台式机来说,这些假设也不是一个有效的假设。

多线程不只是线程之间非常快速的上下文切换,给人一种并行处理的错觉,但实际上并不是在处理吗?

实际上,如果您在一个内核上运行多个线程,那么线程之间的上下文切换需要很长时间(数百条硬件指令)。而且它们很少发生。

但是如果你假设只有一个核心/超线程,那么线程不能并行执行是正确的。

那么,既然CPU要执行的指令数是一样的,那么不管是单线程还是多线程,完成的时间不应该是一样的吗?如果是,不是说多线程是一种并行处理的手段是错误的吗?

如果您假设只有一个内核/超线程可用,那么您的结论是正确的。但是,这种假设在现代计算机上通常不正确。

例如,我使用 3 年的戴尔笔记本电脑的 CPU 具有 2 个内核和每个内核 2 个超线程,这可以提供 4 倍的理论加速(由于硬件并行性!!)。 (这还没有考虑使用 GPU 的可能性……)

请注意,典型的服务器级机器每个刀片有 2 或 4 个 CPU,甚至可能更多。一些服务器级 CPU 达到 16 核或更多。所以单台电脑有 64 核的情况并不少见。


1 - 普通 Java 不会使用 GPU 进行一般计算,所以这有点牵强。

【讨论】:

  • Are there (at least) 10 physical cores available to run the 10 threads? 具有超线程的 5 个物理内核(每个内核 2 个线程)怎么样?假设这 10 个线程真的不相交,假设5 physical cores * 2 threads per core = 10,所有 10 个线程会并行运行吗?
  • 一般来说,操作系统会尝试将超线程视为物理内核。所以是的。超线程并行运行……在硬件层面;见en.wikipedia.org/wiki/Hyper-threading
【解决方案2】:

是的,Java 本质上是多线程的。一个 Java 程序可以有许多不同的线程独立且连续地执行。同一页面上的三个 Java 小程序可以一起运行,每个程序从 CPU 获得相同的时间,而程序员只需很少的额外工作。

这使得 Java 对用户输入非常敏感。它还有助于提高 Java 的健壮性,并提供一种机制,使 Java 环境可以确保恶意小程序不会窃取主机的所有 CPU 周期。

不幸的是,多线程与 Java 紧密集成,这使得 Java 很难移植到 Windows 3.1 或 PowerMac 等本身不支持抢占式多线程的架构。

与多线程相关的成本。多线程之于 Java 就像指针运算之于 C 一样,也就是说,它是极难发现错误的来源。尽管如此,在简单的程序中,可以不使用多线程并且通常没问题

【讨论】:

  • 虽然这是正确的并且解释得很好,但我不认为这实际上是对用户问题的回答(“多线程执行是一种错觉吗?”)。
  • 据我所知,他需要知道是java多线程,好吧,也许我的英语水平有点差,我根据我的理解回答了这个问题,无论如何谢谢,我应该删除答案吗?
【解决方案3】:

您的解释假设一个单 CPU 系统。即使在这种情况下,假设所有线程都属于同一个进程也是错误的。

考虑两个进程同时运行。第一个进程有一个长时间的阻塞操作(即 I/O、磁盘访问)。当 CPU 等待此操作完成时,如果没有多线程,它将不得不等待空闲。但是多线程在复杂的调度算法的支持下启用上下文切换,从而最大限度地利用 CPU。

我上面提到的示例可以应用于具有多线程的单个进程。一个执行阻塞操作,另一个不执行。

【讨论】:

    【解决方案4】:

    如果您的系统具有多个 CPU 或每个 CPU 多个内核,则 JVM 可以利用这些资源并并行运行线程。您可以获得真实的并行处理速度优势。

    可用的 CPU 内核数是多线程代码并行处理速度优势的上限。由于开销和其他效率低下,您无法达到(例如,使用 4 核系统的整整 4 倍)的速度,但您可以使用经过精心设计以利用并行处理的代码接近。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-02
      • 2020-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-01
      • 2013-07-06
      相关资源
      最近更新 更多