首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Go调度系列--GMP状态流转(四)

Go调度系列--GMP状态流转(四)

原创
作者头像
小许code
发布2023-03-31 09:26:33
发布2023-03-31 09:26:33
1.1K00
代码可运行
举报
文章被收录于专栏:小许code小许code
运行总次数:0
代码可运行

前言

在GMP中各个元素在调度器的调度下其实有各种不同的状态转换,比如goroutine就定义了比如_Gidle、_Grunnable、_Grunning、_Gsyscall和_Gwaiting这些状态,在不同的场景中实现这些状态进行不同的转换。

G状态转换

goroutine的状态在runtime/runtime2.go中,_Gidle中被定义为iota,声明为一个无类型整数序号 0,其他定义的枚举逐步进行递增。

代码语言:javascript
代码运行次数:0
运行
复制
// _Gidle means this goroutine was just allocated and has not
// yet been initialized.
_Gidle = iota // 0

_Grunnable // 1
...

Goroutine 枚举的这些状态有以下几种:

  1. _Gidle = 0 goroutine刚刚被分配并且还没有被初始化
  2. _Grunnable = 1 没有执行代码,没有栈的所有权,存储在运行队列中
  3. _Grunning = 2 可以执行代码,拥有栈的所有权,被赋予了内核线程 M 和处理器 P
  4. _Gsyscall = 3 正在执行系统调用,没有执行用户代码,拥有栈的所有权,被赋予了内核线程 M 但是不在运行队列上
  5. _Gwaiting = 4 由于运行时而被阻塞,没有执行用户代码并且不在运行队列上,但是可能存在于 Channel 的等待队列上。若需要时执行ready()唤醒
  6. _Gdead = 6 没有被使用,可能刚刚退出,或在一个freelist;也或者刚刚被初始化;没有执行代码,可能有分配的栈也可能没有;G和分配的栈(如果已分配过栈)归刚刚退出G的M所有或从free list 中获取

其中有几个状态是不用去理会的:_Genqueue_unused(目前未使用)_Gcopystack=8 (不在运行队列上) _Gpreempted=9 (没有执行用户代码) _Gscan=10 GC (没有执行代码,可以与其他状态同时存在 )

G状态流转
G状态流转

M状态转换

M本身其实是无状态的,不过我们可以根据M是否空闲,执行代码,休眠等这些情况将M的列举一些当前行为。

  1. 自旋中:(spinning) M正在从运行队列中获取G,这个时候M拥有一个P
  2. 执行代码:M正在执行go代码,此时M拥有一个P
  3. 执行原生代码中:M正在执行原生代码或者阻塞的syscall,此时的M不会拥有P
  4. 休眠中:M发现无待运行的G时会进入休眠,并添加到空闲M链表中
M状态
M状态

P状态转换

p的底层结构和状态枚举跟g在同一个文件中,主要定义了一下几种状态:

代码语言:javascript
代码运行次数:0
运行
复制
const (
   _Pidle = iota
   _Prunning
   _Psyscall 
   _Pgcstop
   _Pdead
)

type p struct {
   id          int32
   status      uint32 // one of pidle/prunning/...与状态相关  
   ...
   runq     [256]guintptr //p本地队列 默认容量为256个G
   runnext guintptr  //下一个将要运行的G
}
  • Pidle:当前p尚未与任何m关联,处于空闲状态
  • Prunning:当前p已经和m关联,并且正在运行g代码
  • Psyscall:当前p正在执行系统调用
  • Pgcstop:当前p需要停止调度,一般在GC前或者刚被创建时
  • Pdead:当前p已死亡,不会再被调度
P状态流转
P状态流转

在P创建之初或结束gc后,会被置为Pgcstop状态,在完成初始化之后,会进入Pidel状态,进入该状态后的P可被调度器调度,当P与某个M相关联时,会进入到Prunning状态,当其执行系统调用时,会进入到Psyscall状态,当P应为全局P列表的缩小而被删除时会进入Pdead状态,不会再进行状态流转和调度。当正在执行的P由于某些原因停止调度时,会统一流转成Pidle空闲状态,等待调度,避免线程饥饿。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • G状态转换
  • M状态转换
  • P状态转换
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档