【问题标题】:What resources do threads compete for other than CPU and memory除了 CPU 和内存,线程还竞争哪些资源
【发布时间】:2021-07-10 19:00:05
【问题描述】:

在 Brian Goetz 等人的《Java Concurrency in Practice》一书中:

如果线程池太大,那么线程会争夺稀缺的 CPU 和内存资源,从而导致更高的内存使用率和可能的资源耗尽。如果它太小,则吞吐量会受到影响,因为尽管有可用的工作,但处理器仍处于未使用状态。

这意味着如果我们在线程池中创建了太多的线程对象,那么它们会消耗太多的内存。此外,如果我们有太多线程(例如 10 个 CPU 内核的 1000 个线程,有 1000 个任务提交到线程池),那么每个任务将被分配给一个内核,但可能在它完成之前被抢占,然后另一个任务将分配给核心。因此,由于抢先式调度,每个任务可能都需要很长时间才能完成。

线程是否正在竞争其他资源?

【问题讨论】:

  • 这是无法回答的。这完全取决于线程在做什么:如果它们正在访问数据库,那么它们会竞争数据库,如果它们访问磁盘/网络/一些同步的代码块/其他任何东西,它们就会竞争那些。如果您可以命名可以竞争的资源,那么有人可以编写竞争它的线程。
  • 但是由于我们有 10 个内核,因此在任何给定时间只有 10 个线程会访问数据库(即使我们在池中有 1000 个线程),那么为什么拥有更多线程会对此产生任何影响数据库访问?
  • 您可以运行比内核更多的线程。 CPU 可以将一些时间用于一个,然后将一些时间用于另一个,等等。如果这些“时间”不同步(注意:它们不会),那么您可以拥有比您更多的活动数据库连接有核心。

标签: java multithreading


【解决方案1】:

对于 Java 线程堆栈,我不是 100% 确定,但在 Linux 下,如果分配了内存,它会使用共享零页进行初始化。并且实际上没有使用页框(物理内存)。只有当一个线程要写入零页时,才会出现缺页并实际分配页框(写时复制)。

所以如果一个线程不使用它的大部分堆栈,它应该消耗很少的内存。当然,在最坏的情况下,每个线程都可能消耗其所有堆栈,因此会消耗大量内存。

如果您有 CPU 密集型任务,那么您可能不想拥有比 CPU 内核更多的任务。否则你会在上下文切换(包括冷缓存)、TLB 未命中等后果上浪费时间。

关于资源:太多太多提及。

【讨论】:

    【解决方案2】:

    如果缓存被线程共享并推出旧缓存条目为新条目腾出空间(这是典型情况),则线程可以被视为竞争缓存资源。

    如果存在配置了最大大小的缓存,则线程受益的缓存中的每个条目(通过存在于缓存中帮助它节省时间的条目)都是其他线程无法使用的条目。理想情况下,线程使用类似的缓存条目,并且线程通过帮助彼此预加载资源来与其他线程协作。但是如果线程不使用类似的缓存条目,尤其是当缓存很小的时候,添加条目到缓存中的线程将不得不从缓存中删除旧条目,这往往是最近没有执行的其他线程使用的条目.在极端情况下,可能会出现 cache thrashing:当一个线程运行时,它会推出 all 其他线程使用的条目,因此每当一个线程恢复执行时,它就会发现共享缓存有 no 项对其有益。如果 缓存未命中 的惩罚很高,那么这种缓存抖动尤其严重。

    这个问题最重要的例子是内存缓存,尤其是更小更快的缓存 (L1)。

    如果文件系统使用硬盘进行存储,则磁盘臂的位置就像一个条目缓存,对于缓存未命中具有非常大的惩罚:我见过一个多线程文件系统扫描器(想想Unix find 程序)由于磁盘抖动而无法达到单线程扫描程序的性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-16
      • 2017-04-06
      • 2020-02-13
      • 2011-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多