You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Golang中实现合理并行?1.5+版本goroutines是否支持并行?

并行(Parallelism)与并发(Concurrency)的区别,以及Go中Goroutines的并行能力

嘿,咱们先把并行和并发这俩容易搞混的概念掰明白,再聊你关心的Go里goroutines的事儿!

先分清核心区别

  • 并发(Concurrency):重点是处理多个任务的能力,这些任务不需要同时运行,而是通过快速切换执行来“看起来同时进行”。比如你一边煮咖啡一边刷消息,同一时刻你其实只在做一件事,但切换速度快,给人一种同时处理的错觉。
  • 并行(Parallelism):重点是同时运行多个任务的能力,得有多个独立的执行单元(比如多核CPU的不同核心)同时干活。就像你和室友分工,你煮咖啡他刷消息,真正的“同一时间做不同事”。

Go中Goroutines的并行能力到底咋样?

你提到的GOMAXPROCS确实是关键:

  • 在Go 1.5之前,GOMAXPROCS的默认值是1,这意味着Go runtime只会用一个OS线程来调度所有goroutines。哪怕你开了上百个goroutines,它们也只能在这一个线程里交替执行——这时候只有并发,没有并行,因为同一时刻只有一个goroutine在跑。
  • 从Go 1.5开始,GOMAXPROCS的默认值改成了机器的CPU核心数。这时候Go runtime可以把goroutines调度到多个OS线程上,而这些线程可以分配到不同的CPU核心上同时运行。

那你问的“自1.5版本起goroutines天生具备并行性”这个结论,不完全准确——应该说:
在多核机器上,当GOMAXPROCS保持默认值(等于核心数)时,goroutines具备了实现并行的条件,但不是所有goroutines的执行都是并行的:

  • 如果你的goroutines是计算密集型任务(比如大量数学运算),且数量≥2,Go runtime会把它们调度到不同的核心上,这时候就是真正的并行运行。
  • 如果你的goroutines大多是IO阻塞型任务(比如等待网络请求、文件读写),Go runtime会把阻塞的goroutines挂起,调度其他goroutines到线程上,但这时候可能不需要用到多个核心,还是并发的模式。

举个直观的例子

下面是一段计算密集型的代码,在多核机器上运行时,两个goroutines会并行执行,总耗时会接近单个goroutine执行时间的一半:

package main

import (
    "fmt"
    "time"
)

// 模拟计算密集型任务
func heavyCompute(id int) {
    fmt.Printf("Goroutine %d 开始执行\n", id)
    for i := 0; i < 1e8; i++ {
        // 空循环模拟大量计算
    }
    fmt.Printf("Goroutine %d 执行完成\n", id)
}

func main() {
    startTime := time.Now()

    // 启动两个计算goroutines
    go heavyCompute(1)
    go heavyCompute(2)

    // 等待goroutines完成(实际项目建议用sync.WaitGroup,这里用Sleep简化)
    time.Sleep(3 * time.Second)

    elapsed := time.Since(startTime)
    fmt.Printf("总耗时:%v\n", elapsed)
}

如果是在单核机器上运行,两个goroutines会交替执行,总耗时会接近单个goroutine的两倍,这就是纯并发的情况。

内容的提问来源于stack exchange,提问作者Josep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:10:08