
上QQ阅读APP看书,第一时间看更新
1.2.3 go func()调度流程
接下来一起来推演一下,如果执行一行代码go func(),则在GPM模型上的概念里会执行哪些操作。
(1)通过go func()创建一个Goroutine,如图1.18所示。

图1.18 go func()创建Goroutine
(2)有两个存储G的队列,一个是局部调度器P的本地队列,另一个是全局G队列。新创建的G会先保存在P的本地队列中,如果P的本地队列已经满了,就会保存在全局的队列中,如图1.19所示。
(3)G只能运行在M中,一个M必须持有一个P,M与P是1:1的关系。M会从P的本地队列弹出一个可执行状态的G来执行,如果P的本地队列为空,则会从全局队列进行获取,如果从全局队列获取不到,则会向其他的MP组合偷取一个可执行的G来执行,如图1.20所示。
(4)一个M调度G执行的过程是一个循环机制,如图1.21所示。
(5)当M执行某一个G时如果发生了syscall或者其余阻塞操作,则M会阻塞,如果当前有一些G在执行,runtime则会把这个线程M从P中移除(Detach),然后创建一个新的操作系统线程(如果有空闲的线程可用就复用空闲线程)来服务于这个P,如图1.22所示。

图1.19 go func()新建G的放置位置

图1.20 go func()获取G的方式

图1.21 go func()M调度G是循环往复的
(6)当M系统调用结束时,这个G会尝试获取一个空闲的P执行,并放入这个P的本地队列。如果获取不到P,则这个线程M会变成休眠状态,加入空闲线程中,然后这个G会被放入全局队列中,如图1.23所示。