Go GPM 模型

GPM 模型

golang 在系统调度的基础上实现了自己的 goroutine 调度器,即 GPM 模型。goroutine 相比线程更加轻量,GPM 调度器效率更高,因此 go 可以有很强的并发能力


image.png

G:goroutine
P:Processor,相当于 G 的CPU,数量等于 GOMAXPROC
M:执行 G 的线程
GPM 简单原理:

每个 P 都有一个局部队列,负责保存待执行的 G,当局部队列满了就放到全局队列中

每个 P 都有一个 M 绑定,正常情况下 M 从局部队列中获取 G 执行

M 可以从其他队列偷取 G 执行(work stealing),也可以从全局队列获取 G 执行

当 G 因系统调用(syscall)阻塞时会阻塞 M,此时 P 会和 M 解绑(hand off),并寻找新的空闲 M,若没有空闲 的M 就会新建一个 M

当 G 因 channel 或者 network I/O 阻塞时,不会阻塞 M,M 会寻找其他 runnable 的 G;当阻塞的 G 恢复后会重新进入 runnable 进入 P 队列等待执行

mcache(内存分配状态)位于 P,所以 G 可以跨M调度,不再存在跨 M 调度局部性差的问题

G 是抢占调度。不像操作系统按时间片调度线程那样,Go 调度器没有时间片概念,G 因阻塞和被抢占而暂停,并且 G只能在函数调用时有可能被抢占,极端情况下如果 G 一直做死循环就会霸占一个 P 和 M,Go 调度器也无能为力。

GODEBUG

使用 GODEBUG 可以查看 Go 调度器的实际过程:

#含义就是每1000ms,打印输出一次goroutine scheduler的状态
GODEBUG=schedtrace=1000 ./goutils 

#输出
gomaxprocs:P 的数量

idleprocs:空闲的 P

threads:总线程数

spinningthreads:自旋线程数

idlethreads:空闲线程数

runqueue:全局队列中 G 的数目

[2 3 3 2 1 1 2 1]:局部队列中 G 的数目
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容