Skip to content
Go 并发与运行时 · 第 1 篇 / 共 4 篇
领域编程与框架
专题Go 专题
当前序列Go 并发与运行时
阅读位置第 1 篇 / 共 4 篇当前专题第 1 个序列 / 共 3 个序列

goroutine 调度器到底在做什么

goroutine 调度器的核心任务只有一句话:把大量用户态协程,尽量低成本地分配到有限的线程和 CPU 上执行,同时在阻塞、唤醒和抢占之间维持整体吞吐。

先说结论

  • 调度器解决的是“海量协程如何高效运行”,不是“并发逻辑如何自动正确”
  • 重点要看 GMP 三者分工,而不是只记一个 GMP 名词
  • 真正影响性能的,通常是阻塞点、抢占时机和任务分布是否均衡

核心边界

G、M、P 各自负责什么

  • G 是 goroutine,本质上是待执行任务
  • M 是内核线程,真正占用系统线程资源
  • P 是调度上下文,负责本地运行队列、缓存和执行资格

可以把它理解成:任务很多,工人有限,工位数量也有限。调度器要做的是让工人尽量别闲着,也尽量别因为一个慢任务把全局拖住。

调度器为什么比线程模型更轻

goroutine 初始栈很小,切换主要发生在用户态,成本比线程切换低很多。所以 Go 才能比较自然地支持几十万级别的并发任务。

但这不等于 goroutine 没成本。协程数过多、频繁创建销毁、长时间阻塞 syscall,一样会把调度器拖慢。

哪些场景最容易影响调度效果

  • 大量 goroutine 被系统调用阻塞
  • 单个 goroutine 长时间占用 CPU,导致其他任务得不到运行机会
  • 任务分布不均,本地队列很忙而其他 P 空闲
  • GC、网络轮询、定时器回调和业务协程同时争用执行机会

实战里怎么判断

先分清是 CPU 忙还是阻塞多

如果系统 CPU 很高,先看是否存在热点循环、忙等、锁竞争;如果 CPU 不高但延迟上升,优先看网络阻塞、磁盘 IO、数据库调用和 channel 堵塞。

再看调度器有没有失衡

线上排查时,常见信号是 goroutine 数暴涨、请求 RT 抖动、PProf 里大量时间耗在调度或等待上。此时重点不是继续加 goroutine,而是减少无效并发和阻塞传播。

最后看并发模型有没有选错

不是所有场景都适合“一请求一堆 goroutine”。如果任务强依赖共享状态、外部 IO 慢、上游限流严格,盲目加协程只会放大抖动。

常见误区

goroutine 很轻,所以可以无限开

轻量不等于零成本。每个 goroutine 都会占栈、调度元数据和上下文切换成本。

GOMAXPROCS 调大就一定更快

它只决定可并行执行的 P 数量,不会自动解决锁竞争、IO 阻塞和业务热点。

调度器能替你兜底并发设计问题

调度器只负责“怎么跑”,不负责“跑得对不对”。channel、锁、context 和超时控制依然要自己设计好。

一句话总结

理解 goroutine 调度器,关键不是背 GMP,而是知道任务如何排队、线程如何承载、阻塞后如何恢复,以及什么情况下调度本身会成为性能瓶颈。

延伸阅读相关文章优先当前专题,再补跨专题关联。
同一序列 · 顺着当前主线继续读有缓冲 channel 和无缓冲 channel 怎么选适合把 goroutine、channel、context 和锁选择放到一起理解。Go 专题 · Go 并发与运行时同一序列 · 顺着当前主线继续读context 的超时、取消和传播边界适合把 goroutine、channel、context 和锁选择放到一起理解。Go 专题 · Go 并发与运行时同专题其他序列 · Go 并发模型与服务工程化context 传递截止时间和链路信息的边界适合把 goroutine 生命周期、context 边界、接口抽象和优雅停机放回 Go 服务实践里思考。Go 专题 · Go 并发模型与服务工程化同专题其他序列 · Go 工程实践与内存治理Go 服务项目目录怎么组织更稳适合把逃逸分析、GC、错误处理和项目布局放在一条工程主线上看。Go 专题 · Go 工程实践与内存治理跨专题关联 · 同场景:基础学习@Conditional 系列注解怎么配合使用适合把自动装配、条件装配、Profile 和循环依赖放回 Spring Boot 启动过程里理解。Spring 专题 · Spring Boot 启动、装配与配置跨专题关联 · 同场景:基础学习保留策略和日志压缩适合哪些场景适合把副本机制、acks、批量压缩和日志组织放在一条 Kafka 投递主线上理解。Kafka 专题 · Kafka 投递链路与日志存储机制
继续阅读Go 并发与运行时当前序列第 1 篇 / 共 4 篇当前专题第 1 个序列 / 共 3 个序列
往前看
上一序列MyBatis 性能与写入治理从第 1 篇开始:MyBatis 分页插件和 Count 优化
往后看
下一篇有缓冲 channel 和无缓冲 channel 怎么选继续当前序列下一章下一序列Go 工程实践与内存治理从第 1 篇开始:Go 逃逸分析怎么影响性能

把零散经验整理成可查、可复用、可持续更新的企业级知识门户