1. GMP 调度模型
GMP 模型概述
GMP 是 Go 运行时调度器的核心模型:
| 角色 | 说明 |
|---|---|
| G (Goroutine) | 协程,包含栈、程序计数器、状态等信息 |
| M (Machine) | 操作系统线程,真正执行代码的载体 |
| P (Processor) | 逻辑处理器,持有本地 Goroutine 队列 |
全局队列 本地队列
[G][G][G] → P[G][G][G] → M(OS线程)
P[G][G][G] → M(OS线程)Q: 为什么引入 P?
P 的引入实现了工作窃取(Work Stealing):
- 每个 P 持有本地 G 队列,减少锁竞争
- 当某个 P 的队列为空时,可以从其他 P 的队列尾部窃取 G
- P 的数量由
GOMAXPROCS控制,默认为 CPU 核心数
Q: Goroutine 的调度时机?
- 函数调用(编译器插入调度检查点)
- 系统调用(M 与 P 解绑,等待 IO)
runtime.Gosched()主动让出- 通道操作阻塞
- GC STW
Q: 协程和线程的区别?
| 对比项 | 线程 | Goroutine |
|---|---|---|
| 创建开销 | MB 级栈 | 初始 2KB,动态增长 |
| 切换开销 | 内核态切换,微秒级 | 用户态切换,纳秒级 |
| 数量 | 千级别 | 百万级别 |
| 调度 | OS 调度 | Go Runtime 调度 |