golang调度过程

1.运行时系统相关模块

这一节只讲述调度系统。

2. 与调度相关的有下列数据有:

(1)全局表就不用多解释, 调度器不是一个专门的线程,而是一种资源,每个M都可能会对其进行查询,如:M的调用的时候,会首先查找调度器中的可运行队列G,然后查找本地P运行队列; 在M不够的时候,会首先调度器空闲的M列表中查找; 在程序运行过程中,使用 runtime.GOMAXPROCS 接口设置P上下文数量的时候,会动态的增长P的数量,这些P就是加入到调度器的空闲列表。
(2)M每次调用G的时候,必定需要一个上下文P,因为当调用的时候,可能会产生另外的G,其G的取得的步骤为, 从当前P自由G列表中取-> 从调度器自由G列表中取 -> 全局分配。当然,当该P运行完一个G后,会首先加入到P自由G列表,然后超过数量则加入到调度器自由G列表中。

3. M,P,G的对应关系

M 默认是多个, 也就是对应多个OS线程,无状态变化,唯一的变化就是是否在空闲队列中。

3.1 P的状态介绍
P可以通过runtime.GOMAXPROCS设置,一般不用设置。P具有状态:


状态机如下:

(1)M与P关联后,会从Pidle -> Prunning
(2)P变成Pdead状态,只有用户设置了P的数量减少了

3.2 G的状态介绍


状态机图:

(1)Grunning -> Gwaiting 这个状态是Golang自己的channel接收机制造成
(2)Grunning-> Gsyscall 是该协程使用了某些系统调用,如IO读取,所以直接挂起,使用的是异步IO阻塞机制

4. M,P,G运行过程:

注意:上面的全力查找注释有误,为没有则 M会挂起阻塞,然后等待被其他M唤醒
其中,全力查找可运行G的过程会通过以下几步
(1)查找本地P可运行G队列
(2)从调度器可运行G队列查找
(3)从网络IO轮询器中查找就绪G
(4)偷取别人的本地P可运行队列G
(5)再次查找调度器中的可运行G
(6)尝试从所有P中查找可运行队列G
(7)再从网络IO轮询器中查找
实在不行,就把自己和P解除联结,放置到调度器空闲队列中,并且阻塞。

其中查找到多个运行G之后的流程图如下:

5.G IO操作的运行过程
(1)当G执行IO操作后, 并且如果 该G和M已经绑定,那么G阻塞(阻塞只是打个标记,并不是阻塞当前线程),IO请求由IO轮询器进行,然后M继续运行 ,把当前的P解除关联,M阻塞等待,当IO轮询器执行完后,然后G变成可运行状态,当其他的M找到这个绑定M的G,会把自己的上下文P解除联结,并且唤醒绑定的M,然后继续运行。
注意:当未使用G和M绑定的时候,就不会执行唤醒其他M的操作

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值