12

在 Windows 8 中使用花哨的新任务管理器,我注意到对我来说是一个惊喜,当前使用/运行的线程大约 1k。

因为我刚刚对多线程软件和游戏背后的教程和理论产生了共鸣。我的假设是,如果您想从软件中获得最佳性能,那么当有工作要做时,每个逻辑处理器应该始终至少有一个线程。因为该处理器否则将“未使用”。

但是看到我已经在运行大约 1000 个线程,难道所有处理器都已经开始工作了吗?

如果其他 50 个左右的进程已经在使用处理能力,为什么还要使用多线程?管理所有这 1000 个线程不会占用足够的 CPU 资源吗?为什么我作为程序员应该处理线程而不是操作系统?如果它给每个进程一个线程,我的软件不是仍然是“多线程”的吗?

使用更多线程只是一种更高级的进程优先级方式吗?

4

3 回答 3

24

我会说,可能不会。虽然这个问题有点修辞,但请看一下 Jeffrey Richter 撰写的这篇文章/书籍摘录,停止疯狂(来自CLR 通过 C#的书)。它只讨论你问的那些事情。

如果我们只关心原始性能,那么任何机器上的最佳线程数都与该机器上的 CPU 数量相同。[...] 所有线程仍然有一个内核对象、内核模式堆栈和其他分配给它们的资源。这种因为便宜而随意创建线程的趋势必须停止。线程并不便宜——相反,它们很昂贵,所以要明智地使用它们。

我强烈推荐那本书。非常值得从前到后阅读,虽然它相当大,约 900 页。

多线程虽然是一个非常复杂的主题,并且不能简单地用几行来回答,但它高度依赖于您要实现的目标。与往常一样,这取决于您必须测量/评估/优化任何解决方案以获得最佳性能。但是,一般来说,只是例行地抛出线程可能不是一个好主意。附带说明一下,托管线程分配 1 MB 堆栈内存,这意味着在 .NET 应用程序中创建(并保持)线程可能非常浪费。

此外,仅仅因为胎面存在并不意味着它正在消耗完整的核心。它可能会做一些工作,但它也可能会闲置并等待一些工作发生(这是最有可能的情况,否则您的整体 CPU 消耗将不断接近 100 而不是 0)。然而,它们确实消耗,或者更准确地说,浪费了系统资源。

尽管引入了许多技术以使它们更易于使用(各种并行框架等),但引入线程会给您的应用程序增加大量额外的复杂性。但是,潜在的复杂性仍然存在,有时伪装成无害的,但随时准备爆发出它的真实本质(时序问题、死锁、调试复杂性等)。

简而言之,您可能会说,“除非有理由,否则不要使用多线程”。
即便如此,t(h) 还是轻描淡写。

于 2013-02-20T19:20:53.213 回答
8

我喜欢 Jokob 的回答,我觉得大部分重要的观点已经提出:

  • 1k 线程(全局)并不意味着它们完全运行:它们可能都在等待
  • 一般来说,考虑系统中的全局线程数是非常具有误导性的(请参阅下面的说明)
  • 线程(不仅)用于并行编程:它们用于需要多行执行的情况(例如,当您阻塞等待网络响应时,但您仍需要更新 UI 并使其保持响应,或者当您在同一进程中执行低优先级任务(拼写检查、代码检查等)时,...)。毕竟,线程早在多核 CPU 之前就已经存在并且很有用了!
  • 然而现在我们经常看到“疯狂”:线程太多。这并不新鲜:早期网络(网络?)服务器的第一个案例之一:每个连接一个线程(!)。愚蠢,浪费。我们继续,现在我们使用线程池(以及更精致的东西,比如 I/O 完成端口)和(最近的)异步编程。

然而,即使在线程池的情况下,线程数也是每个进程的(除非您使用系统线程池,从 Windows2000 开始可用);因此,如果您有 50 个进程,每个进程都希望从 4 核系统中获得最大优势,那么您在全球范围内拥有合理数量的 200 个线程(并且,通常,线程池的最佳内核数约为 2 倍,以获取 I/O 块和等待考虑)。

这是很自然的,你必须考虑每个进程,而不是整个操作系统。想想如果你对所有进程使用一个有硬限制的集中式线程池会发生什么。假设一个应用程序接受所有这些:你有什么选择?不,你不能有一个硬的、操作系统范围的限制。每个应用程序基本上都是独立的。这是“现代”(1990 年代)操作系统强制执行的模型,这些操作系统基于隔离进程和虚拟私有地址空间,例如 NT 和 Linux:您在操作系统中独处,不应该关心其他操作系统(有时这是强烈的强制执行,例如在内存的情况下)

于 2013-02-28T13:33:08.313 回答
0

简单来说,操作系统让所有应用程序都感觉像是在自己的机器(计算机)上运行。例如,32 位应用程序理论上有 4GB 内存,而物理计算机有 2GB。操作系统正在使用分时多路复用等技术来提供此功能。通过这种机制,您可以观察到这 1K 个线程。(我在一个连接了 28 个用户的终端服务器上看到了 72K。)由于创建线程是昂贵的,程序员只创建一次线程,当任务通过诸如互斥锁、信号量等机制完成时让线程休眠......

那是因为你看到很多线程和 1% 的 CPU 使用率。如果您想查看线程使用了多少 CPU 资源,请查看线程或应用程序的 CPU 时间。这为正在发生的事情提供了更多线索。

于 2013-03-02T23:12:29.333 回答