Race-free doesn’t mean deterministic
In this article about the Go race detector, I emphasize that violating the Memory model with unprotected concurrent accesses is a serious error.
I must add that fixing the data races doesn’t make a program execution trace deterministic. There can still be “races” in the sense of “first goroutine that takes a lock accesses first”, in an order that can’t be predicted.
Consider this program:
The race detector doesn’t emit any warning during its execution, as the write accesses to a are properly serialized thanks to the mutex mu.
$ go run -race not-racy.go
33
However, 2 goroutines are effectively racing to access the shared variable a. The lock guarantees that one of the accesses will always happen-before the other access. The specific order of the accesses may change the next time the program is executed.
In the two cases, the following unfortunate situation was successfully avoided: