Golang调度器GMP原理
Golang调度器由来
- 单进程时代不需要调度器
早期的操作系统每个程序就是一个进程,直到一个程序运行完,才能进行下一个进程
单进程操作系统面临问题:
1 |
|
- 多进程/线程
多进程/多线程的操作系统中,解决了阻塞的问题,因为一个进程阻塞CPU可以立刻到其他进程中执行
多进程面临的问题:
1 |
|
- 协程
(N:1关系)
1 |
|
(M:N关系)
Go语言的协程 goroutine
Go使用groutinue
和channel
,来提供更容易使用的并发.
Goroutine特点:
1 |
|
G: 标识Groutinue
M: 标识thread
线程
Goroutine调度器 GMP模型
G: 标识Groutinue
M: 标识thread
线程, P: Processor
在Go中,线程是运行goroutine的实体,调度器的功能是把可运行的goroutine分配到工作线程上
1 |
|
Groutine调度器和OS调度器是通过M结合起来的,每个M都代表一个内核线程,OS调度器负责把内核线程分配到CPU的核心上执行
- 有关P和M的个数问题
P的数量:
1 |
|
M的数量:
1 |
|
M与P的数量没有绝对关系,一个M阻塞,P就会去创建或者切换另一个M,所以,即使P的默认数量是1,也有可能会创建很多个M出来.
- P和M何时会被创建
1 |
|
调度器的设计策略
复用线程: 避免频繁的创建,销毁线程1
2
3
4
5
6
7
8
91. Work Stealing机制
当本线程无可运行的G时,尝试从其他线程绑定的P中偷取G,而不是销毁线程
2. Hand off 机制
当本线程因为G进行系统调用阻塞时,线程释放绑定的P,把P转移给其他空闲的线程执行
2.1: 利用并行,GOMAXPROCS设置P的数量,最多有GOMAXPROCS个线程分布在多个CPU上同时运行.
2.2: 抢占: 在Goroutinue最多占用CPU10ms,防止其他Goroutinue饿死,
2.3: 全局G队列: 当M执行work stealing从其他P偷取不到G时,可以从全局G队列获取Ggo func() 调度流程
特殊的M0和G0
1 |
|
参考资料
Golang调度器GMP原理
https://blog.chyidl.com/2024/02/20/go调度器/