3 回答
TA贡献1873条经验 获得超9个赞
你的附录是正确的。这里有不同的调度程序。一种是操作系统调度程序,另一种是应用程序级别。查看这篇文章。这正是您要寻找的:
正如我们在第一篇文章中讨论的那样,操作系统调度程序是一种抢占式调度程序。[...] 内核正在做决定,一切都是不确定的。
和这个:
Go 调度程序是 Go 运行时的一部分,并且 Go 运行时内置于您的应用程序中。这意味着 Go 调度程序在内核之上的用户空间中运行。Go 调度器的当前实现不是抢占式调度器,而是协作式调度器。作为协作调度程序意味着调度程序需要在代码中的安全点发生的定义明确的用户空间事件来做出调度决策。
结论是,有两个不同的调度器。一个用于进程,一个用于 Goroutines。
TA贡献1798条经验 获得超3个赞
这里有几件事。首先,维基百科文章谈论的是操作系统级别的抢占,这可能并不完全适用。Go 例程调度不是由操作系统处理,而是由 Go 运行时处理。
本质上,进程/线程由操作系统/硬件处理并且是抢占式的。Go 运行时可以在同一个线程上运行不同的“go routines”。(事实上 ,这是使 Go 独一无二的一件事 - 轻松允许您创建具有数百万个并发 go-routines 的应用程序。)
最初 go-routines 不是抢占式的,但令人惊讶的是这导致了一些问题,但是没有遇到抢占点的长时间运行的循环可能会占用线程。但多亏了 Austin Clements 的一些出色工作,这个问题在几年前就得到了解决(Go 1.15?)。所以我相信 go-routines 至少在更流行的架构上是完全可抢占的,但你可能会遇到旧的评论,否则会这样说。
我希望这有助于回答您的具体问题:
但不是每个进程或任务都是抢占式的……吗?
是的,但它们不是例程。
CPU 调度程序选择下一个进程,但 Go 调度程序负责 goroutines/线程。
不,操作系统(使用 CPU/MMU 硬件设施)调度进程和线程。Go 调度程序只决定在它控制的特定线程上接下来运行哪个 go-routine,并且它永远不会控制超过 GOMAXPROCS(非阻塞)线程。
TA贡献1831条经验 获得超10个赞
我的回答建立在 Andrew 和 Daniel 的回答之上,并且完全基于这次谈话。
从 go 1.14 开始,go 调度器是非合作抢占的。每个 go routine 在一定的时间片后被抢占。在 go 1.19.1 中是10ms 。
在我之前提到的演讲中,从 20:35 开始,您可以找到关于调度程序如何在 1.0 中使用纯协作抢占的历史,然后是编译器在 go 1.2 中烘焙抢占,最后是当前的性质 - 非-合作先发制人。
- 3 回答
- 0 关注
- 101 浏览
添加回答
举报