七叶笔记 » golang编程 » golang协程调度详解之GMP模型

golang协程调度详解之GMP模型

什么是GMP?

G

golang协程

M

内核线程(真正执行计算的资源)

P

逻辑处理器(队列)

调度器生命周期

•1 go func() 创建G•2.1 放入局部队列•2.2 如果局部队列已满则放入全局队列•3 M1 获取G 进行计算•3.1 M1 从P的本地队列中获取一个G绑定进行计算•3.2 如果本地队列为空则从全局队列获取•3.3 从其他的MP组合中窃取G•4 调度•5 执行G.func()•5.1 如果G.func()发生systemCall/阻塞 (systemCall:程序从内核请求服务的一种编程方式)•5.2 创建一个M 或者从休眠队列中获取一个M•5.3 接管当前正在阻塞的G中的P•6 销毁G•7 返回

可能发生阻塞的情况

•Channel上 send or receive•I/O•阻塞的系统调用•定时器•互斥锁

多个运行队列

•本地运行队列•全局运行队列•网络轮询器

队列轮询顺序

•本地•全局•网络•窃取

Channel阻塞或者I/O阻塞情况下的调度:

G被放到wait队列里面,然后M尝试运行下一个runnable的G,没有的话M解绑P进入Sleep State,阻塞完成唤醒G 标记为runnable放到P的队列中等待执行.

System Call阻塞情况下的调度:

这种情况下执行G的M也要解绑P,与G一起进入Sleep状态,如果此时有空间的M,则P与其绑定继续执行G,如果没有则创建新的M. 阻塞的G完成syscall后,G会去尝试获取一个可用的P,如果没有将G标记为Runnable,之前Sleep的M再次Sleep.

相关文章