go 如何知道tcpconn已断开_图解Go语言并发模型MPG

8584848da879e08503433a39f056b998.png

说到并发,初学者对于这个概念经常和并行混淆。其实我们可以从字面意思很容易的理解他们。并发,就是同时发生,而并行,就是同时进行。

以咖啡店为例,两人排两队同时点咖啡,而接到订单一个咖啡师做两杯咖啡,这是并发。两个咖啡师同时工作,每人做一杯咖啡,这是并行。同理回到程序中,多线程程序在单核上运行,就是并发;多线程程序在多核上运行,就是并行。

Go语言的并发不同于Python基于多线程编程模型,而是采用了基于消息并发模型的方式。它将基于CSP模型的并发编程内置到了语言中,通过一个go关键字就可以轻易地启动一个Goroutine,而且在Goroutine之间是共享内存的。

在Go语言中通过自己的调度器实现了CSP模型,这个调度器也就是MPG调度模型:

e7cea688bb7797089f93d8c9e85f3c7b.png
MPG

M 代表内核线程;

P 代表程序执行上下文,将等待执行的G与M对接。Go的运行时系统会适时地让P与不同的M建立或断开关联,以使P中的那些可运行的G能够及时获得运行时机;

G代表协程,可以有多个;

图中两个M如果运行在一个CPU上就是并发,如果运行在不同CPU就是并行。

知道了MPG模型,那Go语言的MPG又是怎样实现调度的呢?下面通过图解来看一下。

对于一个运行的GO程序,在调度器内部存在着:
1. 全局M,P,G列表,分别用于记录当前所有的M,P,G信息;

2. 空闲M,P,G列表,分别用于记录当前空闲可调度的M,P,G信息,以减少M,P,G的创建从而提升性能;

3. 可运行G列表,存放等待调度器分配给P的G。

ba87515956aa88545ca68cc1bae447e9.png

MPG调度器只关注单独的Go程序中的Goroutine,如上图的G0。Go Goroutine采用的是半抢占式的协作调度,只有在G0发生阻塞时才会导致调度,否则会依次执行P绑定的其他G;

5d1d066c042522efb2a82c1b6c103196.png

当G0阻塞时,调度器会将P与当前的M0和G0解绑,同时去空闲M列表中找新的M,如果没有则创建M1,绑定P,顺序执行P下的G。

dd4d1ed1da079143455ecd67ad945e12.png

当G0阻塞结束后,调度器会到空闲P列表中为M0找空闲可绑定的P,如果恰巧有P,则继续执行G0。如果没有可用的P,则如下图所示:(注:这个过程中,M1和M0可能并行)

461aef7b898ae25e21ff7f2af6500b85.png

M0被放入空闲列表,等待调度给需要的G;G0被放入可运行的G列表,列表中的G会经由调度再次放入某个P的可运行G队列。

至此一个简单的MPG流程就完成了。实际程序运行在多核下,同时会创建更多的协程,但是MPG的调度流程是一样的。

【来思Go】,Let's Go!欢迎关注留言交流学习!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值