在 Go 语言的调度模型中,工作线程 M 是从哪里获取可执行的 goroutine 的?
考察说明
考查对 Go 调度器核心机制的理解,特别是 M 与 P 和本地队列的关系。
回答思路
- 【回答框架 1】Go 调度器采用 M:N 模型,M 代表操作系统线程,P 代表逻辑处理器,每个 P 维护一个本地可运行队列。M 必须绑定一个 P 才能执行 goroutine,它主要从绑定的 P 的本地队列中获取任务。
- 【回答框架 2】当本地队列为空时,M 会尝试从全局运行队列获取任务,或者从其他 P 的本地队列中窃取一半的任务,这称为 work stealing 机制,目的是负载均衡。
- 【回答框架 3】另外,M 还会检查网络轮询器(netpoller),当有网络事件就绪时,会将对应的 goroutine 放入运行队列。
- 【回答框架 4】获取 goroutine 的优先级顺序通常为:本地队列、全局队列、网络轮询器、其他 P 的窃取,确保高吞吐和低延迟。
- 【关键点 1】M 必须绑定 P 才能执行 goroutine
- 【关键点 2】首选从本地队列获取,其次全局队列、网络轮询器或其他 P 窃取
- 【关键点 3】work stealing 实现负载均衡
- 【易错点 1】不能认为 M 直接从头开始获取,而是依赖 P 的队列
- 【易错点 2】窃取不是任意抢,而是按特定策略转移一半任务