Golang documentation for the condition variables states the following:
In the terminology of the Go memory model, Cond arranges that a call
to Broadcast or Signal “synchronizes before” any Wait call that it
unblocks.
However, the following code (run via go run -race .
) gives a DATA RACE flag:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
m := sync.Mutex{}
c := sync.NewCond(&m)
var a = 10
go func() {
time.Sleep(time.Second)
a = 20
c.Signal()
}()
go func() {
defer m.Unlock()
m.Lock()
c.Wait()
fmt.Println(a)
}()
select {}
}
Why?
Second goroutine gets into Wait()
. After some time (one second) first goroutine makes a signal by invoking Signal()
. I use time.Sleep here to ensure second goroutine first gets into Wait before Signal happens. Since call to Signal()
is synchronized before any Wait()
call that it unblock, I don’t understand how can it be a data race on a = 20
and fmt.Println(a)
.
Since a = 20
is sequenced before c.Signal()
which is synchronized before unblocking c.Wait()
which is sequenced before fmt.Println(a)
, it results a = 20
happens before fmt.Println(a)
thus it shouldn’t have a data race.