Dra-M Dra-M
首页
技术
冥思
哲学
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

莫小龙

保持理智,相信未来。
首页
技术
冥思
哲学
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Java

  • Golang

    • GitLab私服+Go Modules踩坑经验(SSH自定义端口)
    • 【代码片段】我使用的Gin中间处理器(自定义异常处理、日志打印、traceId、跨域配置)
    • 【Java转Go】如何理解Go中的值类型、引用类型、nil
    • 【Java转Go】如何理解面向对象,怎么把Golang用成面向对象的样子
    • Golang 调度器 GMP 原理与调度全分析
    • Go中GMP有哪些状态?
      • G状态转换
      • M状态转换
      • P状态转换
    • 一文搞懂go gc垃圾回收原理
    • Go什么时候发生阻塞?阻塞时,调度器会怎么做?
    • Go netpoller 原生网络模型之源码全面揭秘
    • Goroutine 泄露 - 被遗忘的发送者
    • go map 设计与实现
    • go slice 设计与实现
    • 小白也能看懂的context包详解:从入门到精通
    • go interface 设计与实现
    • 深入理解 go chan
    • go chan 设计与实现
    • 深入理解 go Mutex
    • 深入理解 go sync.Map - 基本原理
    • go sync.Map 设计与实现
    • 深入理解 go sync.Once
    • 深入理解 go reflect - 反射基本原理
    • 深入理解 go reflect - 要不要传指针
  • 编程思想

  • 微服务

  • 中间件

  • Python

  • 运维

  • 技术
  • Golang
小许code
2023-06-05
目录

Go中GMP有哪些状态?

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

# G状态转换

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
...
1
2
3
4
5
6

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 (没有执行代码,可以与其他状态同时存在 )

img

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链表中

img

M状态

# P状态转换

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
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  • Pidle:当前p尚未与任何m关联,处于空闲状态
  • Prunning:当前p已经和m关联,并且正在运行g代码
  • Psyscall:当前p正在执行系统调用
  • Pgcstop:当前p需要停止调度,一般在GC前或者刚被创建时
  • Pdead:当前p已死亡,不会再被调度

img

P状态流转

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


#Golang#GMP
上次更新: 10/23/2024
Golang 调度器 GMP 原理与调度全分析
一文搞懂go gc垃圾回收原理

← Golang 调度器 GMP 原理与调度全分析 一文搞懂go gc垃圾回收原理→

最近更新
01
mosquito配置ws协议
10-23
02
Pip包的离线下载和安装
10-23
03
stable diffusion 相关收藏
02-24
更多文章>
Theme by Vdoing | Copyright © 2019-2024 Dra-M
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式