Golang - 为什么会出现这种竞争条件?
Golang - Why does this race condition occur?
package main
import "fmt"
var quit chan int
var glo int
func test() {
fmt.Println(glo)
}
func main() {
glo = 0
n := 10000
quit = make(chan int, n)
go test()
for {
quit <- 1
glo++
}
}
情况:
上面的程序输出10000。但是当我给n分配一个更大的数字时(例如n := 1000000
),输出将是一个随机数小于n.
我没有调用runtime.GOMAXPROCS()
,所以这两个goroutine不能运行并行。执行 go run -race
以检测竞争条件,最终 没有 任何警告。
问题:
为什么会出现这种竞争情况?
由于 main
和 test
goroutines 之间没有同步,你不知道 test
中的 fmt.Println
调用会在什么时候发生。
当 运行 GOMAXPROCS = 1
时,答案基本上取决于调度程序何时决定停止执行 main
并切换到 test
。循环内的发送操作是调度程序可以切换到另一个 goroutine 的一个点,因此通过足够多的循环迭代,您希望 test
有机会在某个时刻执行。它不一定会在每次 运行 导致结果变化的同一迭代中切换。
至于用race detector来捕捉这个问题,它成功地为我捕捉到了问题:
$ go run -race test.go
==================
WARNING: DATA RACE
Read by goroutine 5:
main.test()
/../test.go:8 +0x6e
Previous write by main goroutine:
main.main()
/.../test.go:18 +0xfe
Goroutine 5 (running) created at:
main.main()
/.../test.go:15 +0x8f
==================
...
package main
import "fmt"
var quit chan int
var glo int
func test() {
fmt.Println(glo)
}
func main() {
glo = 0
n := 10000
quit = make(chan int, n)
go test()
for {
quit <- 1
glo++
}
}
情况:
上面的程序输出10000。但是当我给n分配一个更大的数字时(例如n := 1000000
),输出将是一个随机数小于n.
我没有调用runtime.GOMAXPROCS()
,所以这两个goroutine不能运行并行。执行 go run -race
以检测竞争条件,最终 没有 任何警告。
问题:
为什么会出现这种竞争情况?
由于 main
和 test
goroutines 之间没有同步,你不知道 test
中的 fmt.Println
调用会在什么时候发生。
当 运行 GOMAXPROCS = 1
时,答案基本上取决于调度程序何时决定停止执行 main
并切换到 test
。循环内的发送操作是调度程序可以切换到另一个 goroutine 的一个点,因此通过足够多的循环迭代,您希望 test
有机会在某个时刻执行。它不一定会在每次 运行 导致结果变化的同一迭代中切换。
至于用race detector来捕捉这个问题,它成功地为我捕捉到了问题:
$ go run -race test.go
==================
WARNING: DATA RACE
Read by goroutine 5:
main.test()
/../test.go:8 +0x6e
Previous write by main goroutine:
main.main()
/.../test.go:18 +0xfe
Goroutine 5 (running) created at:
main.main()
/.../test.go:15 +0x8f
==================
...