Open
Description
A program was posted to golang-nuts, with the question “is this code thread [safe]?”
The program has a race: it executes a select
with a default case many times in parallel, and the default case calls close
on a channel. (You can see the race by inserting a runtime.Gosched()
: https://play.golang.org/p/_PWTTCwPgi.)
To my surprise, the program runs without error even with the race detector enabled.
The Go Memory Model defines an order between sends and receives but not between closes and sends or closes and other closes, so I think this is technically a data race (and not just a logic race). The race detector should report it.
src/racy/main.go
:
package main
import (
"fmt"
"sync/atomic"
"time"
)
func main() {
die := make(chan struct{})
i := int32(0)
closed := func() {
select {
case <-die:
atomic.AddInt32(&i, 1)
default:
close(die)
fmt.Println("closed")
}
}
N := 100000
for i := 0; i < N; i++ {
go closed()
}
time.Sleep(10 * time.Second)
fmt.Println(atomic.LoadInt32(&i))
}
$ go version
go version devel +1852573521 Wed Nov 1 16:58:36 2017 +0000 linux/amd64
$ go run -race src/racy/main.go
closed
99999