goroutine的调度模型

goroutinue

goroutinue是Go为了实现高并发提供的用户态线程,是用户自己管理的,运行在内核线程之上。创建的大量的goruntinue会同时运行在一个或者多个内核线程上,因此需要一个调度器来维护管理这些goroutinue,确保所有的goroutinue都有相对公平的机会适用CPU。
goroutinue和内核线程的映射关系为M:N,多个gorotinue可以在多个内核线程上运行。

GMP模型

调度模型由四部分组成,G、M、P、schedt。
G代表goroutinue,每个goroutinue有自己的栈,是调度的实体
M代表Mechine,代表一个真正的内核线程,是真正执行的实体
P代表Processor,是调度器,给M调度不同的G。P是实现goroutinue和内核线程M:N映射关系的关键。P的上线通过GOMAXPROCS来控制,代表有多少个goroutinue可以并行。
schedt:runtime调度用的数据结构,包含了G.、M、P的全局队列和局部队列。

M的状态

M在自旋中,从运行队列中获取一个G,这时M会拥有一个P
M在执行go代码,这时M会拥有一个P
M执行原生代码或syscall,这时M不拥有P
M发现无等待运行的G时会进入休眠状态,将自己添加到空闲M链表中,M不拥有P

P的状态

P是一个抽象的概念,并不代表一个具体的实体,抽象地表示M运行G所需要的资源。P并不代表CPU核心数,而是表示执行go代码的并发度。有一点需要注意的是,执行原生代码的时候并不受P数量的限制。
同一时间只有一个线程(M)可以拥有P, 局部调度器P维护的数据都是锁自由(lock free)的, 读写这些数据的效率会非常的高。
P是使G能够在M中运行的关键。Go的runtime适当地让P与不同的M建立或者断开联系,以使得P中的那些可运行的G能够在需要的时候及时获得运行时机。
通过runtime.GOMAXPROCS函数我们可以改变单个Go程序可以拥有P的最大数量,如果不做设置会有一个默认值。

在runtime初始化时会确认P的最大数量,之后会根据这个最大值初始化全局P列表【runtime.allp】。类似全局M列表,【runtime.allp】包含了runtime创建的所有P。随后,runtime会把调度器的可运行G队列【runtime.schedt.runq】中的所有G均匀的放入全局的P列表中的各个P的可执行G队列 local queue中。

P的五个状态
Pidel,P没有关联M
Prunning,P关联了一个M,M在执行一个G
Psyscall,P中执行的G在进行系统调用
Pgcstop,runtime在进行GC
Pdead,GOMAXPROCS减少了P的数量,多余的P处于dead状态

除了Pdead状态外,在runtimie进行GC的时候,所有P都会编程Pgcstop状态,在GC结束后都转到Pidle,不会恢复到原状态;

G的状态

G被P管理,适用go关键字创建
G的新建,休眠,恢复,停止都收到runtime管理
G执行异步操作时,会进入休眠状态,不占用内核线程
G新建或恢复时,都会添加到运行队列,等待M取出运行。
每个P有自己的local队列,也有全局的队列。

G的状态
Gidle:G被创建但还未完全被初始化。
Grunnable:当前G为可运行的,正在等待被运行。
Grunning:当前G正在被运行。
Gsyscall:当前G正在被系统调用
Gwaiting:当前G正在因某个原因而等待
Gdead:当前G完成了运行

总结

一个G的执行需要M和P的支持。一个M在于一个P关联之后就形成一个有效的G运行环境 【内核线程 + 上下文环境】。每个P都含有一个 可运行G的队列【runq】。队列中的G会被一次传递给本地P关联的M并且获得运行时机。

M 与 KSE 的关系是绝对的一对一,一个M仅能代表一个内核线程。在一个M的生命周期内,仅会和一个内核KSE产生关联。M与P以及P与G之间的关联时多变的,总是会随着调度器的实际调度策略而变化。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LSY_HELLOWORLD

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值