--- tags: [go, golang, go-principle, gmp-scheduler, summary, cheat-sheet] create time: 2026-06-07 16:00 --- # GMP 调度原理 — 知识卡片 ## 概述 本节汇总 GMP 调度模型的全景流程与核心要点,适合作为复习回顾的速查卡片。涵盖 §6:完整生命周期流程图和关键概念总结。 ## 正文 ### 6.1 GMP 全景流程 ```mermaid flowchart TD subgraph Create["创建 goroutine"] NewProc["runtime.newproc
systemstack → newproc1
runqput → LRQ/GRQ"] end subgraph Schedule["调度循环"] ScheduleFn["schedule → findRunnable"] FindR["findRunnable: LRQ → GRQ → netpoll → steal"] Execute["execute → gogo(g)"] end subgraph Yield["让出执行权"] End["goexit1 → goexit0
status=Gdead, gfput"] Gosched["Gosched → gosched_m
status=Grunnable, globrunqput"] Park["gopark → park_m
status=Gwaiting, 上层管理"] end subgraph Preempt["抢占 sysmon"] Sysmon["sysmon 线程"] Retake["retake: syscall + timeout"] Collab["协作式: stackPreempt"] Signal["非协作式: sigPreempt"] end subgraph Recover["恢复执行"] Ready["goready → ready
status=Grunnable, runqput"] end Create --> Schedule Schedule --> Yield Yield --> Recover Recover --> Schedule Sysmon --> Preempt Preempt --> Yield style Create fill:#e3f2fd style Schedule fill:#e8f5e9 style Yield fill:#fff3e0 style Preempt fill:#ffebee style Recover fill:#e8f5e9 ``` ### 6.2 核心要点速查 | 维度 | 要点 | |------|------| | **角色分工** | G = 任务(goroutine),M = 工人(OS 线程),P = 主管(逻辑处理器) | | **队列优先级** | LRQ(无锁 CAS)> GRQ(加锁)> netpoll(IO)> steal(工作窃取) | | **防饥饿** | 每 61 次调度强制检查一次 GRQ | | **LRQ 容量** | 256 个 G;满时触发 `runqputslow` 批量迁移至 GRQ | | **runnext** | VIP 位置,新创建的 G 优先放入,下次调度直接执行 | | **协程状态机** | `_Gidle → _Grunnable → _Grunning → { _Gdead / _Gwaiting / _Gsyscall }` | | **让渡方式** | 结束→回收到 `gfree`;`Gosched`→入 GRQ;`gopark`→`_Gwaiting` 由上层保管 | | **唤醒机制** | `goready → ready`:改状态→`runqput`→`wakep()` | | **系统调用抢占** | `reentersyscall` 解绑 P/M;exitsyscall 快速路径复用 oldP / 慢速路径重新分配 | | **协作式抢占** | 设置 `stackPreempt`,在函数调用/栈检查时响应 | | **非协作式抢占** | Go ≥ 1.14,通过 POSIX 信号注入 `asyncPreempt`,绕过函数调用依赖 | | **sysmon 三板斧** | netpoll(IO 轮询)→ retake(抢占检查)→ GC 触发 | ### 6.3 关键数据记忆点 | 数字 | 含义 | |------|------| | **256** | LRQ 最大容量 | | **61** | 每次 GRQ 强制检查间隔(schedtick) | | **10ms** | syscall 超时阈值、运行抢占阈值(`forcePreemptNS`) | | **4** | work-stealing 最大试探轮数 | | **128** | netpoll epoll_wait 单次最多返回事件数 | ## 关联笔记 - [[hzh/GolangStar/Go语言原理/gmp调度原理/gmp-overview]] — GMP 概览 - [[hzh/GolangStar/Go语言原理/gmp调度原理/gmp-datastructures]] — G/M/P/Schedt 数据结构 - [[hzh/GolangStar/Go语言原理/gmp调度原理/gmp-lifecycle]] — Goroutine 生命周期 - [[hzh/GolangStar/Go语言原理/gmp调度原理/gmp-preemption]] — 抢占式调度机制 - [[hzh/GolangStar/Go面试题库/GMP面试题]] — 高频面试题