使用Mutex进行Goroutine同步:为何结果未达100000?
问题原因分析
你的代码里Mutex其实是生效的,问题出在main goroutine没有等待所有子goroutine执行完毕就提前退出了。
当你启动100000个goroutine后,main函数立刻执行fmt.Println(n),随后程序就会终止——Go运行时会直接结束所有还在运行的子goroutine,导致大部分自增操作根本没机会执行,所以n的结果远小于100000。
修复方案
使用sync.WaitGroup来等待所有子goroutine完成后再输出n,同时可以去掉冗余的同步机制(Mutex和atomic二选一即可):
方案一:保留Mutex,改用普通自增
package main import ( "fmt" "sync" ) func main() { var n int32 = 0 var mutex *sync.Mutex = new(sync.Mutex) var wg sync.WaitGroup wg.Add(100000) // 标记需要等待100000个goroutine for i := 0; i < 100000; i++ { go func() { defer wg.Done() // goroutine结束时标记完成 mutex.Lock() defer mutex.Unlock() n++ // 用普通自增即可,Mutex已保证原子性 }() } wg.Wait() // 阻塞直到所有goroutine完成 fmt.Println(n) // 此时输出100000 }
方案二:保留atomic,去掉Mutex
package main import ( "fmt" "sync" "sync/atomic" ) func main() { var n int32 = 0 var wg sync.WaitGroup wg.Add(100000) for i := 0; i < 100000; i++ { go func() { defer wg.Done() atomic.AddInt32(&n, 1) // atomic操作本身是原子的,无需Mutex }() } wg.Wait() fmt.Println(n) // 此时输出100000 }
补充说明
sync.WaitGroup的核心作用是协调多个goroutine的同步:Add设置等待计数,Done减少计数,Wait阻塞直到计数为0。- 同时使用
Mutex和atomic是冗余的,二者选其一就能保证自增操作的原子性,没必要同时使用。
内容的提问来源于stack exchange,提问作者Richard Chen
相关产品推荐
相关产品推荐

