GO语言并发模型-MPG模型

目录

MPG模型

goroutine发生阻塞

goroutine切换时机

runqueue执行完成


Go语言调度器内部有三个重要的组成部分:M、P、G

  • M是Machine,系统线程。它是由操作系统管理的,goroutine就是跑在M之上的。M是一个很大的结构,里面维护小对象内存cache(mcache)、当前执行的goroutine、随机数发生器等非常多信息。
  • P是Processor,代表程序执行上下文、处理器。P可以看作是一个局部调度器,P将等待运行的G与M进行对接。它维护了一个goroutine队列,即runqueue。GO的运行时系统会让M和P适时地建里或者断开关联。
  • G是goroutine,可以有多个。它包含了栈、指令指针、正在等待地channel,以及其他对调度goroutine的重要信息。

MPG模型

正在执行的goroutine为蓝色,处于待执行的goroutine为灰色。待执行的goroutine都存放于runqueue中,P维护者这个runqueue。每当由新的goroutine被执行,就会加入runqueue。

        其实go语言运行时系统在早期并没有P这个概念,go语言的调度器直接把G分配到适当的M上。但是这样做的问题就是G并发运行时需要向系统申请资源,会带来性能损耗。

        从go的1.1版本开始,在运行时系统中加入了P,由P来管理G对象,M想要运行G时就需要绑定P。这样带来的好处就是,可以在P对象中预先申请一些系统资源,当G需要的时候先向自己的P去申请。P资源如果也不够了,才会去向全局申请资源,而且会多拿一部分资源以供后面的G去使用。

        而且P解耦了M和G的关系。如果有G发生了阻塞,P可以带着其他的G与新的M进行绑定,使得G总是能及时地运行起来,从而提高并发能力。

goroutine发生阻塞

 M1可能是新被创建的,也有可能是从缓存中直接拿过来的。

当G0发生阻塞时,P会与当前的M0、G0解绑。M1与P进行绑定,继续执行P下的其他的goroutine。

goroutine切换时机

运行过程中必然发生goroutine的切换。阻塞的协程被切换,运行可以运行的协程。

以下操作可能会阻塞,而引起goroutine的切换:

  • select操作(如无可执行case会引起阻塞)
  • I/O操作
  • 等待锁
  • channel(读写操作都是阻塞的)
  • 显示操作切换runtime.Gosched()
  • 程序调用time.Sleep(n * time.Second)

runqueue执行完成

当由Processor的runqueue执行完成,为空时。他会从其他的Processor上偷取一半的goroutine。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值