Goroutine的调度分析(二)

  Go 是用C写的,对于Goruntime,主要有三个数据将结构(其实是4个,后面会讲)支持着goruntime记录着所有的信息以及调度。

G

  G数据结构代表一个goroutine。他保存着goroutine的栈和当前的状态。当然也保存着它将要运行的code的一些相关信息。如下图所示
这里写图片描述

M

  M数据结构代表系统线程,它有保存全局goroutine队列的指针,当前运行G的指针,它自己的cache.

SCHED

  Sched数据结构是一个单个的,全局的数据结构,它记录着不同的G和M的队列,以及一些其他保证调度器可以有序跑起来的信息。有两个G队列,一个是当前可以跑的goroutine的队列,另外一个是空闲的G队列。只有一个跟M有关系的G队列并且是调度器保持的。M队列中M是空闲的并且是waiting to work的状态。Sche的数据结构如下图
这里写图片描述
  runtime一开始需要执行若干个G。一个用来垃圾回收,一个用来调度,一个代表着用户的G code。初始化的时候,一个M被创建,用来启动runtime。当程序跑起来的时候,很多G可能会被用户程序创建,所有有可能需要更多的M来运行这些用户的G。所以runtime可能会提供更多的线程(最多有GOMAXPROCS个激活线程)
  因为M代表着线程,并且M是用来执行goroutine的。所以一个当前没有相关G的线程会从全局队列中取一个G并且执行这个G。如果这个G要求M阻塞,例如进入了系统调用没那么其他的M就会从全局M队列中唤醒。这样做事为了阻塞的M上的goroutine仍然可以被执行。
  系统调用强制线程阻塞,阻塞的时间是系统调用的执行时间。如果一个因为G因为系统调用而阻塞,那么执行这个G的M就不能执行其他的G直到系统调用返回。channel通信不会导致M阻塞。系统不知道channel通信,复杂的channel完全由runtime来控制。如果一个goroutine进入了channel call,它可能会blocak,但是执行这个G的goroutine并不会被阻塞。这种情况下,G的状态会被设置成waiting并且M会运行其他的goroutine知道channel 通信完成。这时候G的当前状态会被重新设置为runnable并且会被等待运行。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值