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

Mutex锁未正常生效咨询:Go语言并发累加结果不符预期

问题分析与解决方案

嘿,我来帮你拆解下这个问题:你写的代码里互斥锁的使用其实是没问题的,真正导致结果不稳定的原因是主goroutine没有等待所有子goroutine执行完毕就直接打印total了。

具体问题解释

当你在main函数里启动10个go add()协程后,main函数并没有停下来等它们跑完,而是直接执行了fmt.Printf语句。这时候大部分协程可能还在执行循环,甚至有些还没开始运行,所以你打印出来的total只是当前时刻的中间值,自然每次运行结果都不一样。而且更关键的是,一旦main函数执行完毕,整个程序就会退出,所有还在运行的子协程都会被强制终止,哪怕它们还没完成任务。

修正方案:使用sync.WaitGroup等待协程完成

我们可以用sync.WaitGroup来跟踪所有子协程的执行状态,确保main函数在所有协程都跑完之后再打印结果。修改后的代码如下:

package main
import (
    "fmt"
    "sync"
)
var total int
var locker sync.RWMutex
func add(wg *sync.WaitGroup) {
    // 协程执行完毕后通知WaitGroup减少计数
    defer wg.Done()
    for x := 1; x <= 100; x++ {
        locker.Lock()
        total += 1
        locker.Unlock()
    }
}
func main() {
    var wg sync.WaitGroup
    // 告诉WaitGroup我们要等待10个协程
    wg.Add(10)
    for x := 1; x <= 10; x++ {
        go add(&wg)
    }
    // 等待所有协程执行完毕
    wg.Wait()
    fmt.Printf("Total is %v\n", total)
}

关键点说明

  • wg.Add(10):提前声明需要等待的协程数量,必须在启动协程之前调用,避免出现协程已经执行完Done()但Add()还没调用的情况。
  • defer wg.Done():确保不管协程是正常完成还是 panic(这里不会,但这是个好习惯),都会通知WaitGroup计数减一。
  • wg.Wait():阻塞main函数,直到WaitGroup的计数归零,也就是所有子协程都执行完毕。

这样修改后,每次运行程序都会稳定输出Total is 1000,完全符合你的预期啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:28:53