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

Go语言两个goroutine对val各自增100次,最终结果总是200的原因是什么?

问题原因分析

首先明确:你提供的代码确实存在数据竞争,运行结果始终为200只是当前运行环境下的概率性表现,并非必然稳定的结果。具体原因如下:

  • val++本质是非原子操作,实际分为三步执行:读取val的当前值、值+1、将新值写回val。没有同步机制的情况下,如果两个goroutine的这三步执行发生重叠,就会出现两次自增实际只让val加1的问题,最终结果会小于200。
  • 你的代码中每次自增后都执行了fmt.Printf打印和time.Sleep(5 * time.Millisecond)休眠操作,这两个操作都会触发Go调度器的调度,大概率让两个goroutine的自增操作完全错开:

单个goroutine执行完一次val++后,会进入IO阻塞/休眠状态,调度器会切换到另一个goroutine执行,此时另一个goroutine执行自己的val++逻辑,两个goroutine的自增三步完全没有重叠,每次自增都能生效,所以最终结果刚好是200。

  • 你可以通过修改代码验证数据竞争的存在:把add函数里的打印和休眠逻辑删掉,再多次运行程序,就会出现最终结果小于200的情况。同时使用go run -race命令运行原代码,Go自带的竞争检测器也会明确报出数据竞争问题。

修改后的验证代码示例:

var val = 0

func main() {
    num := runtime.NumCPU()
    fmt.Println("使用cpu数量", num)
    go add("A")
    go add("B")
    time.Sleep(1 * time.Second)
    fmt.Println("val的最终结果", val)
}

func add(proc string) {
    for i := 0; i < 100; i++ {
        val++
        // 移除打印和休眠逻辑
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 15:45:04