虚拟线程相对于Actor模型或平台线程的主要优势? - Reddit

22-05-05 banq

大多数java服务器使用具有一定线程限制(200、300 ..)的线程池,但是你不受操作系统的限制来产生更多,我已经读过对于linux的特殊配置,你可以达到巨大的数量。
然而,操作系统线程更昂贵,启动/停止速度更慢,必须处理上下文切换(由它们的数量放大),并且您依赖于可能拒绝为您提供更多线程的操作系统。
话虽如此,虚拟线程也消耗相似数量的内存(一篇博客),因此,也存在线程同步和线程上下文复制的问题,那么虚拟线程是如何解决的?

回答:
1、JEP 425回答了您所有的问题,包括您链接到的博客文章中关于内存使用的混淆(这误解了应用程序中大多数虚拟线程的来源和目的)。
简而言之,你可以拥有比平台线程多几个数量级的虚拟线程,虚拟线程不会替换您的应用程序当前使用的平台线程;相反,应用程序中的每个任务都可以产生自己的虚拟线程。

那么,即使在不知道是否存在任何阻塞的情况下,是否建议为事件回调生成新的虚拟线程?
这其实是Actor模型(如果你听说过Akka,那么你就听说过 Actor 模型。)
Loom 是一种在(vanilla)JVM 上实现 Actor 模型的支持技术。
Loom 在组合或并发管理方面并没有真正添加任何东西。

2、虚拟线程不需要消耗类似平台线程的一样多的内存。
对于浅层堆栈(这更常见),虚拟线程的效率要高得多,因为它不会分配满1MB(或你设置的任何东西)。
如果你有类似2000帧的深线程,那么是的,它会使用大量的内存,因为真的没有办法绕过它。
然而,我认为在现实生活中,我所看到的真正疯狂的堆栈的唯一代码是Rxjava/Project reactor的东西,在大多数情况下,Loom可以取代。

3、上下文切换已经是被虚拟线程解决的问题了吗?
上下文切换并不是由虚拟线程 "解决 "的。如果你有100000个由16个平台线程组成的FJ池支持的虚拟线程,而且这些虚拟线程并没有对任何东西进行阻塞,那么只有16个虚拟线程在实际做任何事情。剩下的99984个虚拟线程则是无限期的卡住。

在100000个本机线程中,没有一个是阻塞的,上下文切换是以时间间隔发生的,以确保所有线程都能取得进展。
在100000个线程中,CPU花在执行上下文切换上的时间并不比100个本地线程的运行时间多。

想象一下,每个线程的时间间隔是1ms,而且只有一个CPU核心。无论有多少线程在运行,每秒都会有1000次上下文切换。
如果有100000个线程,每个线程运行1ms,然后暂停近100秒,直到它再次运行。

但是,这与虚拟线程的目的完全相反。它们应该被用于争夺一种不是CPU的资源的时候。在任何时候,大多数虚拟线程都应该处于阻塞状态,即等待IO、信号或锁。

对于共享CPU来说,你显然不能比把任务放在队列中,让cores平台线程处理它们更好。这里有一个权衡:如果你的工作负载有一部分是阻塞和计算的,那么在一个有多个平台线程的调度器上运行虚拟线程是有意义的。

对于正在考虑使用虚拟线程的人来说,这是一件重要的事情,他们需要了解。它们不是银弹,而且在使用不当的情况下可能会导致大问题。

上下文切换的问题并没有被虚拟线程所解决

4、虚拟线程目标之一是避免多重同步。
想象一下,您正在编写一个聊天,您需要在 300-500 个线程中拥有 100,000 个上下文。
您只需运行 100,000 个线程并编写最少的代码。
这是直观且易于理解的。
第二种实现这个聊天的方法是反应式的,但难以编写和调试。
通过Loom虚拟线程,经典编码方法在新的抽象层次上达到了一个新的层次。

1
猜你喜欢