启动调度器
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()
: