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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:55:18