1 package main
2
3 import \"time\"
4
5 func main() {
6 m1 := make(map[string]int)
7 m1[\"hello\"] = 1
8 m1[\"world\"] = 2
9 go func() {
10 for i
The requirements to have a data race are:
In your code all 3 requirements are met:
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.m1
in line #17: m1 = m2
.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
Data race
A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write.
Instructions Reorder
compilers and processors may reorder the reads and writes executed within a single goroutine as far as the reordering does not change the behaviour within the routine, it doesn' ensure behaviour of other goroutines to be unaffected
m2["hello"] = 3
m1 = m2
Can be reordered to
m1 = m2
m2["hello"] = 3
That won't alter the behaviour of the main routine and thus race checking will consider that also for evaluating race condition. Now we have m2["hello"] = 3
causing the race condition and it prints out the same with its original line number