数据竞争(data race),是多个 goroutine 写一个key 导致数据不一致。
在 golang 中一般使用-race参数检测程序的竞争条件;
举个例子
var n int32
wg := &sync.WaitGroup{}
wg.Add(5)
for i := 0; i < 5; i++ {
go func() {
n++
defer wg.Done()
}()
}
wg.Wait()
fmt.Println(n)
启动 5 个 goroutine 修改n的值,执行命令
go run -race main.go
==================
WARNING: DATA RACE
Read at 0x00c0000be01c by goroutine 8:
main.main.func1()
... ...
==================
5
Found 1 data race(s)
exit status 66
找到一个竞争条件,并且已报告行号,接下来尝试第一次修改:
var n int32
wg := &sync.WaitGroup{}
mu := sync.Mutex{}
wg.Add(5)
for i := 0; i < 5; i++ {
go func() {
mu.Lock()
n++
defer mu.Unlock()
defer wg.Done()
}()
}
wg.Wait()
fmt.Println(n)
增加sync.Mutex的互斥锁,保护变量n,执行 go run -race main.go 结果 5 ,看来起效果了!那有没有其他方式方法呢?
接下来第二次尝试
var n int32
wg := &sync.WaitGroup{}
wg.Add(5)
for i := 0; i < 5; i++ {
go func() {
atomic.AddInt32(&n, 1)
defer wg.Done()
}()
}
wg.Wait()
fmt.Println(n)
执行go run -race main.go 结果5,看来atomic也可以对变量进行保护。
是否有其他方式?还带模式!
总结
- 使用
sync.Mutex保护变量,锁偏重 - 使用
atomic保护变量,轻量