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

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

问题描述

Java教程说,创建线程很昂贵。但是为什么它是昂贵的?当创建一个Java线程使得它的创建昂贵时,究竟发生了什么?我的声明是真的,但我只是对JVM中线程创建的机制感兴趣。


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




By Brian Goetz,Tim Peierls,Joshua Bloch,Joseph Bowbeer,David Holmes,Doug Lea

打印ISBN-10: 321-34960-1

解决方案

Java线程创建很昂贵,因为涉及到一些工作:




  • 必须为线程堆栈分配和初始化大块内存。

  • 需要进行系统调用

  • 需要创建,初始化描述符并将其添加到JVM内部数据结构中。



这也是昂贵的,因为线程绑定资源,只要它是活的;例如线程栈,任何可从堆栈到达的对象,JVM线程描述符,OS本地线程描述符。



所有这些都是平台特定的,但它们不便宜






Google搜索找到了一个基准,报告线程创建速率为每秒〜4000的Sun Java 1.4.1上的2002年复古双核处理器至强运行2002年复古Linux。一个更现代的平台会给更好的数字...我不能评论的方法...但至少它给 线程创建可能是昂贵的。



Peter Lawrey的基准测试表明,线程创建在这些天的绝对数量上明显更快,但不清楚这是由于Java和/或操作系统的改进...还是...更快的处理器速度。但如果你使用线程池,而不是每次创建/启动一个新线程,他的数字仍然表示150+的改进。 (而且他指出这是相对的...)






比起绿色线程,但现代的JVM都使用本机线程来提高性能,绿色线程可能更便宜,但是你在其他地方支付。)






我做了一些挖掘,看看一个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)
pre>

根据 man mmap MAP_ANONYMOUS 使得内存初始化为零。



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


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.

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.

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

解决方案

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

  • A large block of memory has to be allocated and initialized for the thread stack.
  • System calls need to be made to create / register the native thread with the host OS.
  • Descriptors needs to be created, initialized and added to JVM internal data structures.

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.

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


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'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 faster 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 ...)


(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.)


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.)

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)

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

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天全站免登陆