Go 里的并发(Concurrency)和并行(Parallelism) ,是面试高频、也是理解 goroutine 的核心。给你一套能讲清 + 能拿分的版本👇
🎯 一句话核心区别
并发是"同时处理多个任务的能力",并行是"同时执行多个任务的能力"。
🧠 一、并发(Concurrency)
👉 重点:任务可以交替执行
即使只有 1 个 CPU 核心,也能并发。
示例
go task1()
go task2()
在单核情况下:
-
执行 task1 一会
-
切到 task2
-
再切回来
➡️ 本质:调度切换
特点
-
不一定同时执行
-
是一种"程序结构设计"
-
Go 用 goroutine + channel 实现
🚀 二、并行(Parallelism)
👉 重点:多个任务真正同时执行
必须依赖:
-
多核 CPU
-
Go 调度器(GMP)
示例
2 核 CPU:
-
task1 在 核1 跑
-
task2 在 核2 跑
➡️ 真正同时执行
特点
-
一定同时执行
-
用于提升计算速度
-
属于"硬件 + 调度能力"
⚙️ 三、Go 是怎么实现的?
Go 的核心设计:
用 goroutine 实现并发,用 GMP 调度实现并行
🔑 关键点
1️⃣ goroutine = 并发单位
不是线程,也不等于并行
2️⃣ 是否并行取决于:
runtime.GOMAXPROCS(n)
👉 默认:
= CPU 核心数
3️⃣ GMP 模型作用
-
G(goroutine)
-
P(调度器)
-
M(线程)
👉 调度流程:
G → P → M → CPU 执行
🍳 四、一个非常好用的类比(面试加分)
并发(一个人做多件事)
一个厨师:
-
一会炒菜
-
一会切菜
-
一会煮面
➡️ 来回切换
并行(多个人同时做)
多个厨师:
-
一个炒菜
-
一个煮面
-
一个切菜
➡️ 同时进行
🔥 五、Go 代码对比(面试常用)
并发(未必并行)
for i := 0; i < 2; i++ {
go func(i int) {
fmt.Println(i)
}(i)
}
time.Sleep(time.Second)
👉 有多个 goroutine,但不保证同时执行
并行(利用多核)
runtime.GOMAXPROCS(4)
👉 允许 4 个线程同时运行
⚠️ 六、常见误区(一定要会)
❌ goroutine = 并行
👉 错,只是并发
❌ 并发一定更快
👉 不一定:
-
有上下文切换开销
-
有锁竞争
❌ 开越多 goroutine 越好
👉 错:
-
CPU 密集 → 会更慢
-
调度压力大
🧩 七、终极总结(面试王炸)
👉 直接这样说:
在 Go 中,并发是通过 goroutine 实现的任务组织方式,而并行是通过 GMP 调度器在多核 CPU 上同时执行多个 goroutine。goroutine 本身不保证并行,是否并行取决于运行环境和调度器配置。