彻底搞懂go GPM

简单理解:https://mp.weixin.qq.com/s/hTgIyJN7p-wrDfLj1bP1wQ

深度理解:https://blog.csdn.net/dream_1996/article/details/118051217

深入方法:https://blog.csdn.net/sydnash/article/details/70304571

总结:

/runtime/proc.go

1、从程序初始化开始

  • 主线程,执行调度器shcedinit ,主线程栈上初始化G0调度器, 创建 GMAXPROC 个P 放到调度器的 pidle 上, 将G0调度器 放到tls(thread local storage) [0] 上 ,主线程创建M0 ,关联上G0,currG, 此时第一个GPM 完成
  • 执行newproc ,获取 P 上空闲的G (状态Gdead),没有则创建第一个 G 放到全局队列, 申请2K栈内存,标记为Grunable, 然后放到P的本地队列,即 runtime.main 这个G在全局队列
  • 执行mstart ,运行 shedule ,找到G0上的P 的G,进行执行,运行runtime.main ->main.main ,运行结束退出

2、在调用go func()的时候,会调用runtime.newproc 有空闲的P,没有空闲的M, wakeup 创建M ,mstart 执行shedule()

阻塞情况

  • 当Channel 等内部调用阻塞 ,G 由_Grunniong 变_Gwaitting,会将G放到wait队列,M会执行下一个G,当没有G时候,M与P 解绑,进入sleep状态,当G被G2唤醒,会尝试加入G2所在P的runnext 、Local队列,全局队列
  • 当在G中遇到系统调用阻塞时,G 变_Gsyscall,M 也处于 block on syscall 时,G所在P与M进行解绑,P找一个空闲的M,没有则创建,执行P上的G2, 当G内系统调用完成后,G会进入空闲的P的local,没有空闲的标记为runable 进入全局队列

goroutine创建流程是什么样子的?

在调用go func()的时候,会调用runtime.newproc来创建一个goroutine,这个goroutine会新建一个自己的栈空间,同时在G的sched中维护栈地址与程序计数器这些信息(下一次在重新获取cpu的时候,这些信息会被重新加载到cpu的寄存器中),这个goroutine会被放到,它所对应的内核线程M所使用的上下文P中的runqueue中

有些goroutine因为调用了runtime.gosched,标记_Grunable,会被放到全局队列中

shedule() 调度

1、1/61 的概率从全局队列获取go,没有获取就会从本地队列获取,再接着从别的p的本地队列,没有的话,就sleep

2、M线程找G0 调度器,将 P 中的G 放到 curentg 位置上,运行结束,取下一个G

  • M 线程 ,执行execute() 获取 g0 ,将g0.m.curg=gp ,gp.m=g0.m (互相 关联 gm)

GPM 

M:os 线程

  • tls 、g0 (M 上的G0 )、currentg ,阻塞、睡眠、唤醒、自旋状态

S:Sched 

  • 全局队列,首尾指针,空闲的M、空闲的P

P:逻辑处理器

  • 有本地队列 256个元素的 循环队列 runq、关联的m

G : 协程go

  • 包含自己的运行栈 stack、被执行的函数 startpc、运行的m、上下文 sched 、下一个G 的指针 schedlink (G 全局队列,就是俩个首尾指针表示)

问题:

m0是主线程初始化时创建,并主动调用mstart()进行循环调度, 那此时只有一个主线程,那其他m1、m2是什么时机被创建并进入各自的schedule循环调度呢?

newproc -> sched 若有空闲的P -> wakeup ->start M

整体执行流程:

  • mstart() => schedule() => findrunnable() => execute() => func() => goexit() => schedule()

M就绪  =>调度 => 查找可调度G => 执行G => 具体方法 => 执行完成 => 继续调度

  • runtime.schedinit初始化Processor数目,最大的Machine数目等等。
  • m0 Machine 代表着当前初始化线程,而 g0 代表着初始化线程 m0 的 system stack
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值