当前位置: 首页 > news >正文

go 中 GOMAXPROCS 详解

GOMAXPROCS 直接关系到:

Go 程序到底能不能“真正并行”。


一句话先说结论

GOMAXPROCS 决定:

同一时间最多有多少个 goroutine 可以并行运行(占用 CPU)。

更准确说:

它决定 P(Processor)的数量。


一、回忆一下 GMP 模型

我们之前讲过:

G = goroutine(任务)
M = 线程(干活的)
P = 调度资源(必须持有才能执行 G)

关键规则:

M 必须拿到 P 才能执行 G

而:

P 的数量 = GOMAXPROCS

二、默认值是多少?

从 Go 1.5 开始:

默认情况下:

GOMAXPROCS = 当前机器可用的 CPU 核心数

更准确地说:

Go 会设置为“当前进程可用的逻辑 CPU 数量”。
默认会把所有可用 CPU 都用上。

什么是“逻辑 CPU”?

不是物理核心数,而是:

  • 包含超线程(Hyper-Threading)

  • 包含容器 / cgroup 限制后的 CPU 数

例如:

  • 4 核 8 线程的机器
    → 默认可能是 8

  • Docker 限制 2 核
    → 默认是 2

例如:

  • 4 核 CPU → 默认 GOMAXPROCS = 4
  • 8 核 CPU → 默认 GOMAXPROCS = 8

你可以打印看看:

fmt.Println(runtime.GOMAXPROCS(0))

传 0 表示“只读取,不修改”。

Go 1.5 开始:

  • 默认值改为 runtime.NumCPU()

  • 不再默认 1

在 Go 1.5 之前:

默认是 1

那时多核不会自动利用。


三、它真正控制的是什么?

很多人误解为:

控制 goroutine 数量 ❌

不是。

它控制的是:

最多同时运行的 goroutine 数量

举个例子:

你开 1000 个 goroutine。

如果:

GOMAXPROCS = 1

那:

  • 任何时刻只有 1 个 goroutine 在真正跑
  • 其他 999 个在排队

如果:

GOMAXPROCS = 4

那:

  • 最多 4 个 goroutine 同时跑在 4 个 CPU 上

四、一个直观类比

想象:

  • goroutine 是工人
  • CPU 是机器
  • P 是机器许可证

你可以雇 1000 个工人(goroutine)

但如果:

只有 4 台机器(P=4)

同时只能 4 个工人干活。


五、代码示例

package mainimport ("fmt""runtime"
)func main() {fmt.Println("Before:", runtime.GOMAXPROCS(0))runtime.GOMAXPROCS(2)fmt.Println("After:", runtime.GOMAXPROCS(0))
}

六、它和并发 vs 并行的关系

并发(concurrency)

  • 可以同时管理很多任务
  • 但未必同时运行

并行(parallelism)

  • 真正同时运行在多个 CPU 上

GOMAXPROCS 决定:

并行度


七、如果设为 1 会发生什么?

runtime.GOMAXPROCS(1)

效果:

  • 所有 goroutine 在一个 P 上调度
  • 仍然可以并发
  • 但不可能多核并行

常用于:

  • 调试调度问题
  • 复现竞态条件

八、为什么不直接用 CPU 核心数?

其实默认就是。

但有些情况你可能想:

  • 限制 CPU 使用
  • 容器环境限制 CPU quota
  • 做性能测试

例如:

GOMAXPROCS=2 ./app

也可以通过环境变量设置。


九、重要理解:P 数量 = GOMAXPROCS

回忆:

一个 P 只能被一个 M 持有
一个 P 同时只能运行一个 G

所以:

最多并行数 = P 数量 = GOMAXPROCS

十、常见误区

❌ 误区 1:GOMAXPROCS 控制 goroutine 总数
→ 错,它只控制同时运行数量

❌ 误区 2:开大一定更快
→ 不一定

如果:

  • CPU 只有 4 核
  • 你设为 100

会:

  • 频繁上下文切换
  • cache 失效
  • 性能反而下降

十一、容器里的坑

在 Docker 里:

如果容器限制 CPU 为 2 核,

但宿主机是 16 核,

老版本 Go 可能仍然认为有 16 核。

新版本 Go 会自动识别 cgroup 限制。


十二、终极总结

可以记住这句话:

GOMAXPROCS 决定 Go 程序能同时使用多少个 CPU 核心。

或者更精确:

它决定 P 的数量,而 P 决定最大并行度。

http://www.jsqmd.com/news/359472/

相关文章:

  • 自然语言处理 - f
  • GMSK调制解调系统的matlab性能仿真,对比维特比解调,1bit差分解调,2bit差分解调
  • 基于Spring Boot的绥大学生学习平台管理系统的设计与实现
  • OAuth是什么?
  • MC ε-Greedy 算法详解
  • 力扣1747-应该被禁止的Leetflex帐户 - 指南
  • APUE笔记:Process Environment(七) - Invinc
  • 401 Unauthorized from POST https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/gener
  • jsp蛋糕甜品店管理系统4fx6j--(程序+源码+数据库+调试部署+开发环境)
  • jsp代理会计企业信息管理系统b4072(程序+源码+数据库+调试部署+开发环境)
  • 在线制作物业管理制度流程图轻松上手无需专业绘图技巧
  • 【题解】Atcoder Beginner Contest 444(ABC444) A~E
  • SampSharp ECS 创建 PlayerTextDraw
  • jsp德育管理系统63rh0--程序+源码+数据库+调试部署+开发环境
  • Excel表格自适应大小设置方法 - 指南
  • 企业元宇宙布局中的AI数据存储:AI应用架构师的5个选择策略
  • 详细介绍:Chromium 140 编译指南 macOS 篇:安装与配置 Xcode(二)
  • jsp党员信息管理系统76673--(程序+源码+数据库+调试部署+开发环境)
  • 给投放 google ads 广告的新手写的一些话
  • 机房管理难题终结者:U位系统解决资源闲置、故障排查慢等核心问题
  • 洛谷 P1368:工艺 ← 双指针 + 解环成链
  • Redis缓冲区溢出及解决方案
  • C++ 内存避坑指南:如何用移动语义和智能指针解决“深拷贝”与“内存泄漏”
  • ros2-赵虚左老师讲义获取
  • 以太网终端主机常用的Command
  • 博泰车联网智能座舱 Android 开发工程师的核心能力与实战挑战
  • 简单制作公司固定资产管理图 新手画图也能快速上手
  • PADS 多层板设计时怎么设置满足3W间距 或 不在某参考层布线
  • 企业级应用:Copilot在团队协作开发中的落地实践
  • 为什么企业都在转向信创RFID?对比传统条码的惊人优势揭秘