在GMP中各个元素在调度器的调度下其实有各种不同的状态转换,比如goroutine就定义了比如_Gidle、_Grunnable、_Grunning、_Gsyscall和_Gwaiting这些状态,在不同的场景中实现这些状态进行不同的转换。
goroutine的状态在runtime/runtime2.go中,_Gidle中被定义为iota,声明为一个无类型整数序号 0,其他定义的枚举逐步进行递增。
// _Gidle means this goroutine was just allocated and has not
// yet been initialized.
_Gidle = iota // 0
_Grunnable // 1
...
Goroutine 枚举的这些状态有以下几种:
其中有几个状态是不用去理会的:_Genqueue_unused(目前未使用)_Gcopystack=8 (不在运行队列上) _Gpreempted=9 (没有执行用户代码) _Gscan=10 GC (没有执行代码,可以与其他状态同时存在 )
M本身其实是无状态的,不过我们可以根据M是否空闲,执行代码,休眠等这些情况将M的列举一些当前行为。
p的底层结构和状态枚举跟g在同一个文件中,主要定义了一下几种状态:
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
}
在P创建之初或结束gc后,会被置为Pgcstop状态,在完成初始化之后,会进入Pidel状态,进入该状态后的P可被调度器调度,当P与某个M相关联时,会进入到Prunning状态,当其执行系统调用时,会进入到Psyscall状态,当P应为全局P列表的缩小而被删除时会进入Pdead状态,不会再进行状态流转和调度。当正在执行的P由于某些原因停止调度时,会统一流转成Pidle空闲状态,等待调度,避免线程饥饿。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。