GMP 模型中的 Goroutine 状态


Go 语言 GMP 模型中的 Goroutine 状态反映了其在调度过程中的不同阶段。以下是各状态的详细说明:


1. _Grunnable(可运行状态)

  • 定义:Goroutine 已准备就绪,等待被分配到操作系统线程(M)执行。
  • 场景
    • 刚被创建的 Goroutine(未开始运行)。
    • 从阻塞状态唤醒(如 channel 有数据可读)。
    • 被抢占或分时调度器主动让出后的状态。
  • 行为
    • 位于本地的 P 运行队列(或全局运行队列)中等待调度。

2. _Grunning(运行中状态)

  • 定义:Goroutine 正在占用一个 M 执行用户代码。
  • 关键规则
    • 一个 P 同一时刻最多有一个 Goroutine 处于此状态(因为 P 绑定到一个 M 上执行)。
  • 场景
    • 正在执行用户逻辑或非阻塞的系统调用。
  • 状态转换
    • 收到抢占信号(如时间片用完或手动调用 Gosched()) → 转为 _Grunnable。
    • 主动阻塞(如等待 channel) → 转为 _Gwaiting。
    • 执行系统调用 → 转为 _Gsyscall(若调用非阻塞)。

3. _Gsyscall(系统调用状态)

  • 定义:Goroutine 正在执行阻塞式系统调用(如文件 I/O、网络请求)。
  • 调度影响
    • 系统调用期间,关联的 M 会被解绑并阻塞,对应的 P 可能会被释放给其他空闲的 M(通过 handoffp 机制)。
  • 状态转换
    • 系统调用完成后,若 M 能立即找回原 P → 重新进入 _Grunning。
    • 若 P 已被抢占 → 转为 _Grunnable,Goroutine 加入全局运行队列等待。

4. _Gwaiting(等待/阻塞状态)

  • 定义:Goroutine 因某些原因主动暂停执行(非系统调用)。
  • 典型场景
    • 等待 channel 的读写操作(如 ch <- data 或 <-ch)。
    • 执行 time.Sleep 或等待定时器。
    • 调用 sync.Mutex.Lock() 时锁被占用。
  • 触发恢复
    • 依赖外部事件(如 channel 数据到达)唤醒,标记为 _Grunnable 并加入运行队列。

5. _Gdead(终止状态)

  • 定义:Goroutine 已完成任务或因异常退出。
  • 行为
    • 资源会被 Go 运行时回收(或缓存复用,避免频繁分配内存)。
    • 无法被调度或执行。
  • 触发条件
    • Goroutine 执行完函数并正常退出。
    • 程序发生 panic 且未被恢复。

附加说明:状态转换与调度策略

  • 抢占机制:长时间占用 CPU 的 _Grunning Goroutine 会被调度器标记为可抢占。
  • 协作式调度:通过函数调用/阻塞操作主动让出运行权,而非严格抢占(Go 1.14+ 支持基于信号的抢占优化)。
  • 生命周期
    _Grunnable → _Grunning → (_Gwaiting | _Gsyscall | _Grunnable) → _Gdead.

理解这些状态有助于分析 Goroutine 的调度行为,定位高并发场景下的性能或死锁问题。

posted @   guanyubo  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2024-02-26 C++ 刷题必备
2024-02-26 利用正则与状态机解析HTTP请求报文,实现处理静态资源的请求
2024-02-26 利用IO复用技术Epoll与线程池实现多线程的Reactor高并发模型
2024-02-26 C++14特性
2024-02-26 webserver服务器学习记录
2024-02-26 Linux内核工作原理
点击右上角即可分享
微信分享提示