首页 > 后端开发 > Golang > 正文

Go 并发程序未并行执行的原因及解决方案

DDD
发布: 2025-08-01 20:24:31
原创
709人浏览过

go 并发程序未并行执行的原因及解决方案

本文旨在解答 Go 语言并发程序未能充分利用多核 CPU 资源,导致程序未并行执行的问题。我们将深入探讨 GOMAXPROCS 的作用,分析其对程序性能的影响,并提供相应的优化建议,帮助开发者编写高效的并发 Go 程序。

在 Go 语言中,goroutine 提供了强大的并发能力,但有时我们会发现,即使程序中使用了多个 goroutine,也无法充分利用多核 CPU 的优势,导致程序未能并行执行。这通常与 GOMAXPROCS 的设置有关。

GOMAXPROCS 的作用

GOMAXPROCS 是一个环境变量或 runtime 包中的函数,用于设置 Go 程序可以同时使用的操作系统线程的最大数量。默认情况下,GOMAXPROCS 的值为 1,这意味着 Go 程序只能使用一个操作系统线程,即使 CPU 有多个核心,goroutine 也只能在一个核心上运行,无法实现真正的并行。

要让 Go 程序利用多核 CPU,需要将 GOMAXPROCS 设置为大于 1 的值。通常,可以将其设置为 CPU 的核心数。

如何设置 GOMAXPROCS

有两种方法可以设置 GOMAXPROCS:

  1. 设置环境变量:

    在运行 Go 程序之前,可以在终端中设置 GOMAXPROCS 环境变量。例如,如果 CPU 有 4 个核心,可以执行以下命令:

    千图设计室AI海报
    千图设计室AI海报

    千图网旗下的智能海报在线设计平台

    千图设计室AI海报 172
    查看详情 千图设计室AI海报
    export GOMAXPROCS=4
    go run your_program.go
    登录后复制
  2. 使用 runtime.GOMAXPROCS 函数:

    可以在 Go 代码中使用 runtime.GOMAXPROCS 函数来设置 GOMAXPROCS 的值。例如:

    package main
    
    import (
        "fmt"
        "runtime"
    )
    
    func main() {
        runtime.GOMAXPROCS(runtime.NumCPU()) // 设置 GOMAXPROCS 为 CPU 核心数
        fmt.Println("GOMAXPROCS:", runtime.GOMAXPROCS(0)) // 打印 GOMAXPROCS 的值
        // ... 你的并发代码 ...
    }
    登录后复制

    runtime.NumCPU() 函数返回 CPU 的逻辑核心数。

示例代码分析与改进

让我们回顾一下原始代码,并添加设置 GOMAXPROCS 的代码:

package main

import (
    "fmt"
    "time"
    "big"
    "runtime"
)

var c chan *big.Int

func sum(start, stop, step int64) {
    bigStop := big.NewInt(stop)
    bigStep := big.NewInt(step)
    bigSum := big.NewInt(0)
    for i := big.NewInt(start); i.Cmp(bigStop) < 0; i.Add(i, bigStep) {
        bigSum.Add(bigSum, i)
    }
    c <- bigSum
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU()) // 设置 GOMAXPROCS 为 CPU 核心数
    fmt.Println("GOMAXPROCS:", runtime.GOMAXPROCS(0)) // 打印 GOMAXPROCS 的值

    s := big.NewInt(0)
    n := time.Nanoseconds()

    step := int64(4)
    c := make(chan *big.Int, int(step))
    stop := int64(100000000)
    for j := int64(0); j < step; j++ {
        go sum(j, stop, step)
    }
    for j := int64(0); j < step; j++ {
        s.Add(s, <-c)
    }
    n = time.Nanoseconds() - n
    fmt.Println(s, float64(n)/1000000000.)
}
登录后复制

通过在 main 函数中调用 runtime.GOMAXPROCS(runtime.NumCPU()),我们可以确保 Go 程序能够利用所有可用的 CPU 核心。

注意事项

  • 并发不等于并行: 即使设置了 GOMAXPROCS,也不能保证程序一定能够并行执行。并发是指程序能够同时处理多个任务,而并行是指程序能够同时在多个 CPU 核心上执行多个任务。Go 的 goroutine 提供了并发能力,但只有当 GOMAXPROCS 大于 1 时,才能实现真正的并行。
  • Context Switching 的开销: 如果程序中存在大量的 goroutine 之间的通信,设置过大的 GOMAXPROCS 可能会导致频繁的 context switching,反而降低程序的性能。因此,需要根据程序的具体情况,选择合适的 GOMAXPROCS 值。
  • Goroutine 调度器的优化: Go 的 goroutine 调度器也在不断优化,未来可能会更好地处理 goroutine 之间的通信,减少 context switching 的开销。

总结

GOMAXPROCS 是控制 Go 程序并行执行的关键参数。通过正确设置 GOMAXPROCS,可以充分利用多核 CPU 的优势,提高程序的性能。然而,需要注意并发不等于并行,以及 context switching 的开销,根据程序的具体情况选择合适的 GOMAXPROCS 值。在编写并发 Go 程序时,理解 GOMAXPROCS 的作用至关重要。

以上就是Go 并发程序未并行执行的原因及解决方案的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

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