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 的调度行为,定位高并发场景下的性能或死锁问题。
Do not communicate by sharing memory; instead, share memory by communicating.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享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内核工作原理