Go 运行时中 Scheduler 的启动初始化流程是怎样的?
考察说明
考查对 Go 运行时调度器启动和初始化机制的理解。
回答思路
- 【回答框架 1】Go Scheduler 初始化主要发生在 runtime.schedinit 函数中,该函数在程序启动时由 runtime 调用,完成调度器核心结构的初始化。
- 【回答框架 2】初始化过程包括设置调度器的互斥锁、M 列表、P 列表、任务队列等数据结构,并初始化空闲 M 和 P 的链表。
- 【回答框架 3】接着会创建第一个 M(即主线程对应的 M0),并将其与当前的 G(主 goroutine)绑定。
- 【回答框架 4】然后根据 GOMAXPROCS 创建相应数量的 P,并将这些 P 放入空闲列表,等待 M 获取。
- 【回答框架 5】最后调用 procresize 函数完成 P 的调整,并启动 sysmon 监控线程,开始调度循环。
- 【关键点 1】schedinit 是调度器初始化的入口,负责核心结构初始化。
- 【关键点 2】第一个 M 对应主线程,主 goroutine 绑定在 M0 上。
- 【关键点 3】P 的数量由 GOMAXPROCS 决定,并通过 procresize 调整。
- 【关键点 4】初始化后启动 sysmon 线程监控调度。
- 【易错点 1】不要将 M 初始化和 P 创建顺序混淆,先有 M0 和主 G,再创建 P。
- 【易错点 2】GOMAXPROCS 默认值在 Go 1.5 后为 CPU 核数,但初始化时可以动态调整。