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++
}
}
Situation:
The above program outputs 10000. But when I assign a bigger number to n (e.g. n := 1000000
), the output will be a random number less than n.
I haven't called runtime.GOMAXPROCS()
, so these two goroutines can't run in parallel. Executing go run -race
to detect race conditions, ends up without any warnings.
Question:
Why does this race condition occur?
As there is no synchronisation between the main
and test
goroutines, you don't know at what point the fmt.Println
call in test
will happen.
When running with GOMAXPROCS = 1
, the answer will essentially depend on when the scheduler decides to stop executing main
and switch to test
. The send operation within the loop is one point where the scheduler can switch over to another goroutine, so with enough iterations of the loop you'd expect test
to get a chance to execute at some point. It isn't necessarily going to switch at the same iteration every run leading to the variation in results.
As for catching this with the race detector, it successfully catches the problem for me:
$ 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
==================
...