Go race condition以及解決方法
阿新 • • 發佈:2018-12-17
形成條件
一般情況下是由於在沒有加鎖的情況下多個協程進行操作對同一個變數操作形成競爭條件.
如果沒有鎖的情況會輸出結果非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語言的設計思想.