Go runtime 调度器精讲(五):调度策略为哪种?
摘要:原创文章,欢迎转载,转载请注明出处,谢谢。 0. 前言 在 第四讲 我们介绍了 main goroutine 是如何运行的。其中针对 main goroutine 介绍了调度函数 schedule 是怎么工作的,对于整个调度器的调度策略并没
原创文章,欢迎转载,转载请注明出处,谢谢。
0. 前言
在 第四讲 我们介绍了 main goroutine 是如何运行的。其中针对 main goroutine 介绍了调度函数 schedule 是怎么工作的,对于整个调度器的调度策略并没有介绍,这点是不完整的,这一讲会完善调度器的调度策略部分。
1. 调度时间点
runtime.schedule 实现了调度器的调度策略。那么对于调度时间点,查看哪些函数调用的 runtime.schedule 即可顺藤摸瓜理出调度器的调度时间点,如下图:
调度时间点不是本讲的重点,这里有兴趣的同学可以顺藤摸瓜,摸摸触发调度时间点的路径,这里就跳过了。
2. 调度策略
调度策略才是我们的重点,进到 runtime.schedule:
// One round of scheduler: find a runnable goroutine and execute it.
// Never returns.
func schedule() {
mp := getg().m // 获取当前执行线程
top:
pp := mp.p.ptr() // 获取执行线程绑定的 P
pp.preempt = false
// Safety check: if we are spinning, the run queue should be empty.
// Check this before calling checkTimers, as that might call
// goready to put a ready goroutine on the local run queue.
if mp.spinning && (pp.runnext != 0 || pp.runqhead != pp.runqtail) {
throw("schedule: spinning with local work")
}
gp, inheritTime, tryWakeP := findRunnable() // blocks until work is available
...
execute(gp, inheritTime) // 执行找到的 goroutine
}
runtime.schedule 的重点在 findRunnable()。findRunnable() 函数很长,为避免影响可读性,这里对大部分流程做了注释,后面在有重点的加以介绍。
