-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathraceCatch.go
76 lines (69 loc) · 1.94 KB
/
raceCatch.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package main
import (
"fmt"
"os"
"strconv"
"sync"
)
/*
go run -race raceCatch.go 10
go run raceCatch.go 10
*/
func main() {
arguments := os.Args
if len(arguments) != 2 {
fmt.Println("Give me a natural number!")
os.Exit(1)
}
numGR, err := strconv.Atoi(os.Args[1])
if err != nil {
fmt.Println(err)
return
}
var waitGroup sync.WaitGroup
var aMutex sync.Mutex
var i int
k := make(map[int]int)
k2 := make(map[int]int)
k[1] = 12
/*
The first data race happens inside anonymous `func()`,
which is called by the `for` loop that is called by a goroutine.
The problem here is signified by the Previous write message.
After examining the related code, it is easy to see that
the actual problem is that the anonymous function takes no parameters,
which means that the value of `i` that is used in the `for` loop cannot
be deterministically discerned, as it keeps changing due to the `for` loop,
which is a write operation.
*/
for i = 0; i < numGR; i++ {
waitGroup.Add(1)
go func(j int) {
defer waitGroup.Done()
fmt.Println("k round", j, "write to k using", i)
k[i] = i
fmt.Println("k round", j, "after write is", i)
}(i)
}
for i = 0; i < numGR; i++ {
waitGroup.Add(1)
go func(j int) {
defer waitGroup.Done()
fmt.Println("k2 round", j, "write to k2 using", j)
/*
without `aMutex`,
this anonymous function will cause race again
*/
aMutex.Lock()
k2[j] = j
aMutex.Unlock()
fmt.Println("k2 round", j, "write to k2 using", j)
}(i)
}
waitGroup.Wait()
// until all goroutine ends, we try to mutate the value
k[2] = 10
k2[2] = 10
fmt.Printf("k = %#v\n", k)
fmt.Printf("k2 = %#v\n", k2)
}