0

0

Golang并发与并行的区别解析

P粉602998670

P粉602998670

发布时间:2026-01-16 15:24:54

|

539人浏览过

|

来源于php中文网

原创

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

golang并发与并行的区别解析

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 topps 显示多个线程——Go 的 M 线程数可能远小于 goroutine 数,且很多是休眠态。要看真实 CPU 利用率分布和调度行为。

立即学习go语言免费学习笔记(深入)”;

网胜B2B电子商务系统蓝色风格 2008 SP6.2 普及版
网胜B2B电子商务系统蓝色风格 2008 SP6.2 普及版

  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 更喘不过气。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

178

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

226

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

337

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

208

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

391

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

196

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

191

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

192

2025.06.17

C++ 单元测试与代码质量保障
C++ 单元测试与代码质量保障

本专题系统讲解 C++ 在单元测试与代码质量保障方面的实战方法,包括测试驱动开发理念、Google Test/Google Mock 的使用、测试用例设计、边界条件验证、持续集成中的自动化测试流程,以及常见代码质量问题的发现与修复。通过工程化示例,帮助开发者建立 可测试、可维护、高质量的 C++ 项目体系。

8

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3.8万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号