Golang中我們使用Channel或者sync.Mutex等鎖保護資料,有沒有一種機制可以檢測程式碼中的資料競爭呢?
背景知識
資料競爭是併發情況下,存在多執行緒/協程讀寫相同資料的情況,必須存在至少一方寫。另外,全是讀的情況下是不存在資料競爭的。
使用race檢測資料競爭
go build
有個標記race
可以幫助檢測程式碼中的資料競爭。
➜ awesome git:(master) ✗ go help build
//.... omit
-race
enable data race detection.
Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
下面舉個例子:
package main
import "fmt"
func main() {
i := 0
go func() {
i++ // write i
}()
fmt.Println(i) // read i
}
測試方法:
➜ awesome git:(master) ✗ go build -race hi.go
➜ awesome git:(master) ✗ ./hi
0
==================
WARNING: DATA RACE
Write at 0x00c00009c008 by goroutine 6:
main.main.func1()
/Users/mac/go/src/github.com/mac/awesome/hi.go:9 +0x4e
Previous read at 0x00c00009c008 by main goroutine:
main.main()
/Users/mac/go/src/github.com/mac/awesome/hi.go:12 +0x88
Goroutine 6 (running) created at:
main.main()
/Users/mac/go/src/github.com/mac/awesome/hi.go:8 +0x7a
==================
Found 1 data race(s)
exit status 66
提示示例程式碼存在1處資料競爭,說明了資料會在第9行寫,並且同時會在12行讀形成了資料競爭。
當然你也可以使用go run
一步到位:
➜ awesome git:(master) ✗ go run -race hi.go
0
==================
WARNING: DATA RACE
Write at 0x00c000094008 by goroutine 6:
main.main.func1()
/Users/shitaibin/go/src/github.com/shitaibin/awesome/hi.go:9 +0x4e
Previous read at 0x00c000094008 by main goroutine:
main.main()
/Users/shitaibin/go/src/github.com/shitaibin/awesome/hi.go:12 +0x88
Goroutine 6 (running) created at:
main.main()
/Users/shitaibin/go/src/github.com/shitaibin/awesome/hi.go:8 +0x7a
==================
Found 1 data race(s)
exit status 66
如果這篇文章對你有幫助,請點個贊/喜歡,讓我知道我的寫作是有價值的,感謝。