深入理解 Go | 调度:GMP 模型(第二部分)

启动调度器

Go 程序启动之后,在进入 main() 之前,会调用 runtime.schedinit() 启动调度器:



调度循环

调度器启动后,Go 运行时就会调用 runtime.mstart() 初始化一个新线程,然后调用 runtime.schedule() 进入调度循环(永不返回)。调度循环会查找一个可运行的 goroutine,然后在当前线程上执行这个 goroutine。

可运行 goroutine 的来源有:

  • 全局可运行队列
  • 与处理器 P 绑定的本地可运行队列
  • netpoll
  • 从其他处理器 P 的本地可运行队列中窃取


创建 goroutine

在编译阶段,go fn() 会转换成运行时调用 runtime.newproc()。这个函数在从(本地/全局)空闲 goroutine 列表从获取不到一个可用的 goroutine 才会新建一个。并且,会将 fn 调用的参数和 runtime.goexit() 的 PC 保存在 goroutine 的栈中。



goroutine 执行完毕

在调度 goroutine 运行的时候,runtime.goexit() 位于调用栈的顶端,因此,当 goroutine 对应的函数运行完毕后,就会跳转执行 runtime.goexit()



请言小午吃个甜筒~~