4

Loom会造成CPU密集型线程的不公平调度

 1 year ago
source link: https://www.jdon.com/60826
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Loom会造成CPU密集型线程的不公平调度
Project Loom ( JEP 425 ) 可能是 Java 有史以来最受期待的新增功能之一。它对虚拟线程(或“绿色线程”)的实现保证了开发人员能够创建高度并发的应用程序,例如具有数十万个打开的 HTTP 连接,坚持众所周知的线程每个请求的编程模型,而无需诉诸不太熟悉且通常更复杂的反应式方法。

经过几年的努力,Loom最近才被合并到 OpenJDK 的主线中,并在最新的[url=https://jdk.java.net/19/]Java 19 早期访问版本[/url]中作为预览功能提供。即,现在是接触虚拟线程并探索新功能的最佳时机。

虚拟线程由 JVM调度到操作系统级别的载体线程上。如果应用程序代码遇到阻塞方法,Loom 会从当前的载体上卸载虚拟线程,为其他虚拟线程腾出空间进行调度。
虚拟线程很便宜并且由 JVM 管理,也就是说,您可以拥有很多,甚至数百万。

那么, Loom 的调度器如何知道一个方法正在阻塞?事实证明,它没有。
从Project Loom 的主要作者Ron Pressler那里了解到,情况正好相反:JDK 中的阻塞方法已经针对 Loom 进行了调整,以便在被虚拟线程调用时释放 OS 级别的载体线程:

Java 中的所有阻塞都是通过 JDK 完成的(除非您显式调用本机代码)。我们将 JDK 中的“叶leaf”阻塞方法更改为阻塞虚拟线程而不是平台线程。例如,在所有 java.util.concurrent 中只有一种这样的方法:LockSupport.park

如果代码不是 IO-boundIO密集型,而是 CPU-bound CPU密集型,会发生什么?即,如果虚拟线程中的代码在没有调用任何 JDK 的“叶leaf”阻塞方法的情况下运行一些繁重的计算,那么虚拟线程会怎样?

假设有一组worker执行 CPU 密集型任务,因为没有yield点。您在不同的虚拟线程上启动了许多任务。您希望它们都在同一时间完成。在这种情况下它们不会在同一时间完成,并且完成的时间将随机地大不相同。

在虚拟线程和操作系统级线程的情况下,CPU密集的代码的行为实际上是非常不同的:
有的虚拟线程会一直在执行,而其他虚拟线程则会发生类似被堵塞的现象,等待这些虚拟线程执行一段时间才执行,而不是每段虚拟线程都能公平地轮流被执行。

当然,这种情况只在有超过CPU线程水平的并发全占据CPU的情况下才会发生,不过这还是这引起了大家对公平性的担忧,但这不是一种常见的情况,而且在这种边缘情况下不使用虚拟线程是可以避免的。

在这种情况下,java开发者需要成为一定水平的专家,了解Loom适合哪些使用情况,哪些不适合,这大大增加了错误的概率。
为什么不让Loom在所有情况下都能很好地更容易地工作呢,就像Go语言一样?


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK