为什么说创建一个线程很昂贵? [英] Why is creating a Thread said to be expensive?

查看:56
本文介绍了为什么说创建一个线程很昂贵?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The Java tutorials say that creating a Thread is expensive. But why exactly is it expensive? What exactly is happening when a Java Thread is created that makes its creation expensive? I'm taking the statement as true, but I'm just interested in mechanics of Thread creation in JVM.

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

Thread lifecycle overhead. Thread creation and teardown are not free. The actual overhead varies across platforms, but thread creation takes time, introducing latency into request processing, and requires some processing activity by the JVM and OS. If requests are frequent and lightweight, as in most server applications, creating a new thread for each request can consume significant computing resources.

来自Java并发实践
作者:Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowbeer、David Holmes、Doug Lea
打印 ISBN-10:0-321-34960-1

From Java Concurrency in Practice
By Brian Goetz, Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes, Doug Lea
Print ISBN-10: 0-321-34960-1

推荐答案

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

因为它>>是<<很贵.

Because it >>is<< expensive.

Java 线程的创建代价高昂,因为其中涉及到相当多的工作:

Java thread creation is expensive because there is a fair bit of work involved:

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

如果线程还活着,它就会占用资源,这在某种意义上也是很昂贵的;例如线程堆栈、任何可从堆栈访问的对象、JVM 线程描述符、OS 本地线程描述符.

It is also expensive in the sense that the thread ties down resources as long as it is alive; e.g. the thread stack, any objects reachable from the stack, the JVM thread descriptors, the OS native thread descriptors.

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

The costs of all of these things are platform specific, but they are not cheap on any Java platform I've ever come across.

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

A Google search found me an old benchmark that reports a thread creation rate of ~4000 per second on a Sun Java 1.4.1 on a 2002 vintage dual processor Xeon running 2002 vintage Linux. A more modern platform will give better numbers ... and I can't comment on the methodology ... but at least it gives a ballpark for how expensive thread creation is likely to be.

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

Peter Lawrey's benchmarking indicates that thread creation is significantly faster these days in absolute terms, but it is unclear how much of this is due improvements in Java and/or the OS ... or higher processor speeds. But his numbers still indicate a 150+ fold improvement if you use a thread pool versus creating/starting a new thread each time. (And he makes the point that this is all relative ...)

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

The above assumes native threads rather than green threads, but modern JVMs all use native threads for performance reasons. Green threads are possibly cheaper to create, but you pay for it in other areas.

更新:OpenJDK Loom 项目旨在提供一个轻量级的替代方案到标准 Java 线程,等等.他们提出了虚拟线程,它是原生线程和绿色线程的混合体.简单来说,虚拟线程更像是一个绿色线程实现,它在需要并行执行时使用底层的本地线程.

Update: The OpenJDK Loom project aims to provide a light-weight alternative to standard Java threads, among other things. The are proposing virtual threads which are a hybrid of native threads and green threads. In simple terms, a virtual thread is rather like a green thread implementation that uses native threads underneath when parallel execution is required.

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

As of now (Jan 2021) the Project Loom work is still at the prototyping stage, with (AFAIK) no Java version targeted for the release.

我已经做了一些挖掘以了解 Java 线程的堆栈是如何真正得到分配的.在 Linux 上的 OpenJDK 6 的情况下,线程堆栈是通过调用 pthread_create 创建本机线程来分配的.(JVM 不会向 pthread_create 传递一个预先分配的堆栈.)

I've done a bit of digging to see how a Java thread's stack really gets allocated. In the case of OpenJDK 6 on Linux, the thread stack is allocated by the call to pthread_create that creates the native thread. (The JVM does not pass pthread_create a preallocated stack.)

然后,在 pthread_create 中,通过调用 mmap 来分配堆栈,如下所示:

Then, within pthread_create the stack is allocated by a call to mmap as follows:

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

根据man mmapMAP_ANONYMOUS 标志会导致内存被初始化为零.

According to man mmap, the MAP_ANONYMOUS flag causes the memory to be initialized to zero.

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

Thus, even though it might not be essential that new Java thread stacks are zeroed (per the JVM spec), in practice (at least with OpenJDK 6 on Linux) they are zeroed.

这篇关于为什么说创建一个线程很昂贵?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆