462 字
2 分钟
什么是workstealing
Go scheduler 的职责就是将所有处于 runnable 的 goroutines 均匀分布到在 P 上运行的 M。
当一个 P 发现自己的 LRQ 已经没有 G 时,会从其他 P “偷” 一些 G 来运行。看看这是什么精神!自己的工作做完了,为了全局的利益,主动为别人分担。这被称为 Work-stealing,Go 从 1.1 开始实现。
Go scheduler 使用 M

个人感觉,上面这张图比常见的那些用三角形表示 M,圆形表示 G,矩形表示 P 的那些图更生动形象。
实际上,Go scheduler 每一轮调度要做的工作就是找到处于 runnable 的 goroutines,并执行它。找的顺序如下:
runtime.schedule() { // only 1/61 of the time, check the global runnable queue for a G. // if not found, check the local queue. // if not found, // try to steal from other Ps. // if not, check the global runnable queue. // if not found, poll network.}找到一个可执行的 goroutine 后,就会一直执行下去,直到被阻塞。
当 P2 上的一个 G 执行结束,它就会去 LRQ 获取下一个 G 来执行。如果 LRQ 已经空了,就是说本地可运行队列已经没有 G 需要执行,并且这时 GRQ 也没有 G 了。这时,P2 会随机选择一个 P(称为 P1),P2 会从 P1 的 LRQ “偷”过来一半的 G。

这样做的好处是,有更多的 P 可以一起工作,加速执行完所有的 G。