问题
先看一段代码
func TestCounter(t *testing.T) {
counter := 0
for i := 0; i < 1000; i++ {
go func() {
counter++
}()
}
time.Sleep(time.Second * 1) // 增加时间等待,防止外部的协程比1000个协程先执行结束
t.Logf("counter = %d", counter)
}
代码执行结果:
=== RUN TestCounter
share_mem_test.go:17: counter = 988
--- PASS: TestCounter (1.00s)
PASS
发现计数的结果,小于1000!!!
原因
这个是因为在1000个协程处理的时候,counter处于共享内存,导致并发写数据的时候异常。
解决办法——加锁
func TestCounterForSafe(t *testing.T) {
var mut sync.Mutex
counter := 0
for i := 0; i < 1000; i++ {
go func() {
defer func() {
mut.Unlock() // 解锁
}()
mut.Lock() // 加锁
counter++
}()
}
time.Sleep(time.Second * 1) // 增加时间等待,防止外部的协程比1000个协程先执行结束
t.Logf("counter = %d", counter)
}
运行结果
=== RUN TestCounterForSafe
share_mem_test.go:33: counter = 1000
--- PASS: TestCounterForSafe (1.00s)
PASS
这个时候,发现数据对的上了。
但是有时候我们不知道代码要执行多久,没法准确估计出sleep时间。
优化
func TestCounterForWaitGroup(t *testing.T) {
var wg sync.WaitGroup
var mut sync.Mutex
counter := 0
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer func() {
mut.Unlock() // 释放锁资源
}()
mut.Lock() // 加锁
counter++
wg.Done()
}()
}
wg.Wait() //等到所有的任务执行结束
t.Logf("counter = %d", counter)
}
运行结果
=== RUN TestCounterForWaitGroup
share_mem_test.go:52: counter = 1000
--- PASS: TestCounterForWaitGroup (0.00s)
PASS