GMP模型

本文解释了Go语言中的关键概念:Goroutine(协程)、Machine(工作线程)、Processor(处理器)。讨论了它们之间的关系,如G的存储位置、M和P的协作与抢占式调度,以及M0和G0的角色。
摘要由CSDN通过智能技术生成

G,M,P分别是什么

  • G,Goroutine,就是协程。存储于P的本地队列或者是全局队列中。

  • M,Machine,就是Work Thread,就是传统意义的线程,用于执行Goroutine,G。只有在M与具体的P绑定后,才能执行P中的G。

  • P,Processor,处理器,主要用于协调G和M之间的关系,存储需要执行的G队列,与特定的M绑定后,执行Go程序,也就是G。

上图:

M就是线程,由操作系统负责调度,cpu中执行

G可以存在全局队列,也可存在本地队列(下面会详细讲述,每个本地队列也就是P可以存256个G)

P与M建立联系,在P中执行G(P并不与一个固定的M简历联系如果M阻塞,P会与新的M联系)

GMP的数量问题

        P由cpu的核数决定,一般情况P的数量就是cpu的核数,P的数量可以通过函数:runtime.GOMAXPROCS设置

        G的数量时没有限定的

        M的数量有上限,10000个,但是一般达不到,有几个因素可以影响M的数量:CPU的核数,GOMAXPROCS的数量,操作系统的线程限制

P与G的关联

        新创建的G会首先存在P(本地队列里面),如果P满了,会存到全局队列中,同时把P中的一半的G也放在全局队列里面,之后有新的G还会先存到P里面

那么当P执行G的时候:

首先从P里面查找,本地没有G的时候,从其他的P里面拿G,一般1也是一半, 当所有P都没有的时候 , 从全局队列拿G,一次会获取多个

还有一种情况就是P里面永远有G怎么办:

当全局运行队列中有待执行的 G 时,还会有固定几率(每61个调度时钟周期 schedtick)会从全局的运行队列中查找对应的 G,为了保证全局G队列一定可以被调度。

P与M关联

        只有M才能真正的执行G,所以当要执行G的时候P需要与M关联,(每个M只能同时执行一个G)

当P需要执行,但是没有空闲M的时候,会创建新的M来与P建立联系

当M上的G运行耗时活着阻塞的时候,M与释放P转给其他M执行,当M执行完的系统调用阻塞的G后,M会尝试获取新的空闲P,同时将G放入P的本地队列执行。若没有空闲的P,则将G放入全局G队列,M进入休眠,等待被唤醒或被垃圾回收

M0和G0

  • M0, 启动程序后的编号为 0 的主线程,负责执行初始化操作和启动第一个 G,也就是 main Goroutine。之后与其他M一样调度。

  • G0,每个 M 创建的第一个 Goroutine。G0 仅用于负责调度的 G,G0 不指向任何可执行的函数,每个 M 都会有一个自己的 G0。在调度或系统调用时会使用 G0 的栈空间。

协作和抢占调度

当某个 G 执行时间过长,其他的 G 如何调度。通常有两种方案:

  • 协作式,主动让出执行权,让其他G执行。通过runtime.Gosched()可以让出执行权。

  • 抢占式,被动让出执行权,也就是调度器将G的执行权取消,分配给其他的G。Go目前默认的方式。在Go中一个G最多可以执行10ms,超时就会被让出调度权。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值