形成条件
一般情况下是由于在没有加锁的情况下多个协程进行操作对同一个变量操作形成竞争条件.
如果没有锁的情况会输出结果非1001
.
func main() {
c := 1
g := sync.WaitGroup{}
times := 1000
for i:=0 ; i< times; i++ {
g.Add(1)
go func() {
c++
g.Done()
}()
}
g.Wait()
fmt.Println(c)
}
原因
多核CPU操作同一变量,可能会取到’旧’的值,是一个并发导致的错误.
检查方式
对项目执行竞争检测:
$ go test -race mypkg // test the package
$ go run -race mysrc.go // compile and run the program
$ go build -race mycmd // build the command
$ go install -race mypkg // install the package
可以轻松的看到问题代码:
$ go run -race mtest.go
==================
WARNING: DATA RACE
Read at 0x00c0420080e0 by goroutine 7:
main.main.func1()
C:/Users/liuzexin/go/src/gotest/mtest.go:65 +0x42
Previous write at 0x00c0420080e0 by goroutine 6:
main.main.func1()
C:/Users/liuzexin/go/src/gotest/mtest.go:65 +0x5b
Goroutine 7 (running) created at:
main.main()
C:/Users/liuzexin/go/src/gotest/mtest.go:63 +0xec
Goroutine 6 (finished) created at:
main.main()
C:/Users/liuzexin/go/src/gotest/mtest.go:63 +0xec
==================
989
Found 1 data race(s)
exit status 66
解决方式
方式1:使用互斥锁sync.Mutex
方式2:使用管道
使用管道的效率要比互斥锁高,也符合Go语言的设计思想.