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
相关产品推荐
相关产品推荐

