goroutine 默认实现并发而非并行,是否并行取决于 GOMAXPROCS 设置与 CPU 核心数;仅当 GOMAXPROCS > 1 且存在多 goroutine 可运行时,调度器才分派到多个 P 实现真正并行。

Go 语言里,goroutine 天生支持并发,但**默认不等于并行**——是否真正“同时执行”,取决于 GOMAXPROCS 设置和底层 OS 调度,不是写个 go f() 就自动多核跑满。
为什么 goroutine 是并发而非天然并行
Go 运行时用的是 M:N 调度模型(GPM),即大量 goroutine(G)被复用到少量系统线程(M)上,再由这些线程绑定到 P(逻辑处理器)运行。而 P 的数量默认 = CPU 核心数,但可通过 runtime.GOMAXPROCS(n) 修改。
关键点在于:即使你启动了 1000 个 goroutine,如果 GOMAXPROCS=1,它们依然在单个 P 上交替执行——这是典型的**并发(concurrency)**;只有当 GOMAXPROCS > 1 且有足够多可运行的 goroutine 时,调度器才可能把它们分派到多个 P 上,从而触发真正的**并行(parallelism)**。
- 并发是“能同时处理多个任务”的设计能力;并行是“真正在多个 CPU 核心上同时跑任务”的执行状态
-
go f()只保证启动 goroutine,并不承诺它立刻执行、也不承诺它独占一个核 - IO 密集型场景(如 HTTP server)靠并发就能高效响应;CPU 密集型任务(如矩阵计算)必须开启并行才有效果
如何确认你的程序实际发生了并行
不能只看 go top 或 ps 显示多个线程——Go 的 M 线程数可能远小于 goroutine 数,且很多是休眠态。要看真实 CPU 利用率分布和调度行为。
立即学习“go语言免费学习笔记(深入)”;
websenB2B是一套经过完善设计的B2B行业网站程序,是windows nt系列环境下最佳的B2B行业网产站解决方案。精心设计的架构与功能机制,适合从个人到企业各方面应用的要求,为您提供一个安全、稳定、高效、易用而快捷的行业网站商务系统。分普及版和商业版等不同版本。一、网胜B2B电子商务系统SP6.2蓝色风格普及版本升级功能说明:1、邮件群发功能:可以选择某一级别的会员,并放入支持html
- 用
go tool trace查看 trace 文件,在浏览器中打开后观察「Proc」视图:多个 P 同时处于running状态,才是并行发生 - 用
runtime.NumCPU()和runtime.GOMAXPROCS(-1)检查当前 P 数量;若返回值为 1,基本不可能并行 - 在 CPU 密集循环中加
runtime.Gosched()会破坏并行节奏——它主动让出 P,导致其他 goroutine 抢占,反而降低并行效率
常见并发陷阱:闭包变量捕获 + 并行误判
很多人以为 for 循环里起 goroutine 就是“并行处理每个元素”,结果输出全是最后一个值——这不是并行问题,而是并发下的经典闭包陷阱。
for i := 0; i < 3; i++ {
go func() {
fmt.Println(i) // 全部打印 3
}()
}
原因:所有 goroutine 共享同一个变量 i 的地址,循环结束时 i == 3,它们都读到了最终值。
- 修复方式:传参进 goroutine,如
go func(val int) { ... }(i) - 别混淆“多个 goroutine 同时存在”(并发)和“它们是否真在不同核上跑”(并行)——这个 bug 在并发/并行两种模式下都会发生
- 即使开了
GOMAXPROCS=8,上面代码也照样错;并行只是放大了竞争时机,不解决逻辑错误
什么时候该调大 GOMAXPROCS?
绝大多数 Go 服务(HTTP、RPC、DB 访问)完全不需要手动设置 GOMAXPROCS。默认值(等于物理核数)对 IO 密集型负载已足够。强行设高反而有害。
- 适合调高的场景:纯 CPU 计算密集型,且 goroutine 之间无强同步依赖,例如批量图像转码、加密哈希、数值模拟
- 不适合调高的场景:大量 channel 通信、频繁锁竞争、或依赖全局状态的旧代码——P 增多会加剧调度开销和 cache false sharing
- 设置时机:应在
main()开头尽早调用runtime.GOMAXPROCS(n),晚于 init 阶段可能被 runtime 自动覆盖
真正难的从来不是“怎么开并行”,而是判断“哪里需要并行”——IO 等待多的地方堆 goroutine 就行,CPU 瓶颈处才要拆任务+开多 P;更隐蔽的是,有些“CPU 密集”其实是内存带宽或 GC 压力造成的假象,盲目调高 GOMAXPROCS 只会让 GC 更喘不过气。









