小编典典

为什么说创建线程很昂贵?

all

Java 教程说创建线程很昂贵。但究竟为什么它很贵?当创建一个 Java 线程使其创建成本高昂时,究竟发生了什么?我认为这句话是真的,但我只是对 JVM
中的线程创建机制感兴趣。

线程生命周期开销。线程创建和拆卸不是免费的。实际开销因平台而异,但线程创建需要时间,将延迟引入请求处理,并且需要 JVM
和操作系统进行一些处理活动。如果请求频繁且轻量,就像在大多数服务器应用程序中一样,为每个请求创建一个新线程会消耗大量计算资源。

摘自 Java Concurrency in Practice
作者 Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowbeer、David Holmes、Doug Lea
打印 ISBN-10:0-321-34960-1


阅读 112

收藏
2022-07-14

共1个答案

小编典典

为什么说创建线程 昂贵?

因为它>>是<<昂贵。

Java 线程的创建很昂贵,因为涉及到相当多的工作:

  • 必须为线程堆栈分配和初始化一大块内存。
  • 需要进行系统调用以使用主机操作系统创建/注册本机线程。
  • 需要创建、初始化描述符并将其添加到 JVM 内部数据结构中。

从某种意义上说,只要线程还活着,它就会占用资源,这也是昂贵的。例如线程堆栈、从堆栈可访问的任何对象、JVM 线程描述符、OS 本机线程描述符。

所有这些东西的成本都是特定于平台的,但在我遇到的任何 Java 平台上它们都不便宜。


通过 Google 搜索,我发现了一个旧基准,它报告在运行 2002 复古 Linux 的 2002 复古双处理器
Xeon 上的 Sun Java 1.4.1 上的线程创建速率约为每秒 4000
个。一个更现代的平台将提供更好的数字......我无法评论该方法......但至少它为线程创建可能 有多昂贵提供了一个大概。

Peter Lawrey 的基准测试表明,如今线程创建的绝对速度明显更快,但尚不清楚其中有多少是由于 Java
和/或操作系统的改进......或更高的处理器速度。但是,如果您使用线程池而不是每次创建/启动一个新线程,他的数字 仍然表明提高了 150 倍以上。
(他指出这都是相对的......)


以上假设是原生线程而不是绿色线程,但现代 JVM 出于性能原因都使用原生线程。绿色线程的创建可能更便宜,但您在其他领域需要付费。

更新:OpenJDK Loom 项目旨在为标准
Java 线程提供一种轻量级的替代方案。他们提出了 虚拟线程
,它是本地线程和绿色线程的混合体。简单来说,虚拟线程就像一个绿色线程实现,当需要并行执行时,它在下面使用本机线程。

截至目前(2021 年 1 月),Project Loom 工作仍处于原型设计阶段,(AFAIK)没有针对发布的 Java 版本。


我已经进行了一些挖掘,以了解 Java 线程的堆栈是如何真正分配的。在 Linux 上的 OpenJDK 6
的情况下,线程堆栈由pthread_create创建本机线程的调用分配。(JVM 不传递pthread_create预先分配的堆栈。)

然后,在pthread_create堆栈内通过调用分配mmap如下:

mmap(0, attr.__stacksize, 
     PROT_READ|PROT_WRITE|PROT_EXEC, 
     MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)

根据man mmap,该MAP_ANONYMOUS标志使内存初始化为零。

因此,即使新的 Java 线程堆栈归零(根据 JVM 规范)可能不是必需的,但实际上(至少对于 Linux 上的 OpenJDK 6)它们是归零的。

2022-07-14