首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Coroutines是先发制人,还是只是阻塞了选择可运行线程的线程?

Coroutines是先发制人,还是只是阻塞了选择可运行线程的线程?
EN

Stack Overflow用户
提问于 2021-08-20 12:00:21
回答 2查看 480关注 0票数 1

在深入研究Coroutine的实现(如"Default“和"IO”)之后,我发现它们只包含一个Java执行器(这是一个简单的线程池)和一个Runnable队列(这是coroutine逻辑块)。

让我们以一个示例场景为例,在相同的coroutine上下文中启动10,000个协同器,例如“默认”dispatcher,其中包含一个执行器,池中有512个真正的线程。

这些协同线将被添加到调度器队列中(以防飞行中协同线的数量超过最大阈值)。

例如,让我们假设,我从10,000中启动的第一批512协同任务非常缓慢和沉重。

我的其他协同机制是否会被阻塞,直到至少有一个真正的线程完成,或者在这些“用户空间线程”中是否存在一些时间切片机制?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-08-20 12:18:37

协同调度是协作性的,而不是先发制人的,因此上下文切换只能在暂停点进行.这实际上是设计上的,它使执行速度快得多,因为协同机制不会互相对抗,上下文切换的数量也比抢占式调度中的少。

但正如你注意到的,它也有缺点。如果执行长CPU密集型计算,则建议不时调用产量()。它允许释放线程用于其他协同工作。另一种解决方案是为我们的计算创建一个不同的线程池,以便将它们与应用程序的其他部分分开。这与先发制人的调度有类似的缺点-它将使协同/线程争夺对CPU核心的访问。

票数 3
EN

Stack Overflow用户

发布于 2021-08-20 12:51:57

一旦协同线开始执行,它将继续执行,直到到达暂停点,这是通过调用suspendCoroutinesuspendCancellableCoroutine引入的。

暂停是基本理念。

但是,这是通过设计实现的,因为挂起对于coroutines引入的性能提升至关重要,协同背后的全部原因是,当线程只做等待时,为什么一直阻塞线程(例如同步IO)。为什么不使用这个线程来做其他的呢?

如果没有停职,你就会损失很多性能增益。

因此,为了在特定情况下识别开关,您必须定义术语slow and heavy。cpu密集型任务(如生成素数)可以是慢的和重的,在服务器上执行复杂计算然后返回结果的API调用也可以是慢的和重的。如果512个协同线没有暂停点,那么其他人将不得不等待它们完成。这实际上违背了使用协同线的全部意义,因为您有效地使用coroutiens代替线程,但增加了开销。

如果您必须并行执行一系列非挂起的操作,则应该使用像Executor这样的服务,因为在本例中,协同只会添加一个无用的抽象层.

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68861907

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档