The requirements to have a data race are:
- Multiple goroutines accessing the same resource (e.g. a variable) concurrently.
- At least one of those accesses is a write.
- The accesses are uncynchronized.
In your code all 3 requirements are met:
- You have the main goroutine accesssing
m1
, and the one you start in it also accesses m1
. The main goroutine accesses it after the other goroutine has been launched, so they are concurrent.
- The main goroutine writes
m1
in line #17: m1 = m2
.
- The accesses are not synchronized, you use no mutex or channels or anything like that (sleeping is not synchronization).
Therefore it's a data race.
The obvious data race is between lines #11 reading m1
, and line #17 writing m1
.
But! Since line #17 assigns m2
to m1
, then when/if the launched goroutine continues to run, it attempts to read m1
which may now be the value of m2
because we assigned m2
to m1
. What does this mean? This introduces another data race writing m2
and reading m1
.
That is after line #17 if the program does not end immediately (it may, but not necessarily), then the launched goroutine attempts to read from m1
which is now m2
which was last written in line #16, so this explains the "conflict" between lines #11 and #16.
The full go run -race
output is as follows:
==================
WARNING: DATA RACE
Write at 0x00c42000e010 by main goroutine:
main.main()
/home/icza/gows/src/play/play2.go:17 +0x22f
Previous read at 0x00c42000e010 by goroutine 5:
[failed to restore the stack]
Goroutine 5 (running) created at:
main.main()
/home/icza/gows/src/play/play2.go:9 +0x190
==================
==================
WARNING: DATA RACE
Read at 0x00c42007e000 by goroutine 5:
runtime.mapaccess1_faststr()
/usr/local/go/src/runtime/hashmap_fast.go:208 +0x0
main.main.func1()
/home/icza/gows/src/play/play2.go:11 +0x7a
Previous write at 0x00c42007e000 by main goroutine:
runtime.mapassign_faststr()
/usr/local/go/src/runtime/hashmap_fast.go:598 +0x0
main.main()
/home/icza/gows/src/play/play2.go:16 +0x1fc
Goroutine 5 (running) created at:
main.main()
/home/icza/gows/src/play/play2.go:9 +0x190
==================
==================
WARNING: DATA RACE
Read at 0x00c420080088 by goroutine 5:
main.main.func1()
/home/icza/gows/src/play/play2.go:11 +0x90
Previous write at 0x00c420080088 by main goroutine:
main.main()
/home/icza/gows/src/play/play2.go:16 +0x212
Goroutine 5 (running) created at:
main.main()
/home/icza/gows/src/play/play2.go:9 +0x190
==================
Found 3 data race(s)
exit status 66