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() 函数很长,为避免影响可读性,这里对大部分流程做了注释,后面在有重点的加以介绍。
阅读全文