Я собрал следующий код с флагом «-race» и запустил его (go версия go1.14.1 linux / amd64), и было сообщено о некоторых скачках данных (см. Ниже). Иногда сообщалось только об одной гонке данных, а иногда три. Гонка данных между строками 24 и 35 понятна, но я не могу понять, почему сообщается о гонке данных между строками 24 и 40.
1 package main
2
3 import (
4 "sync"
5 )
6
7 var (
8 m = make(map[string]string)
9 pm = &m
10 updateLock = sync.RWMutex{}
11 )
12
13 func main() {
14 wg := &sync.WaitGroup{}
15 wg.Add(2)
16 go func() {
17 defer wg.Done()
18 handle()
19 }()
20
21 go func() {
22 defer wg.Done()
23 //updateLock.RLock()
24 if _, ok := (*pm)["test"]; ok {
25 }
26 //updateLock.RUnlock()
27 }()
28 wg.Wait()
29 }
30
31 func handle() {
32 newMap := make(map[string]string)
33 update(&newMap)
34 updateLock.Lock()
35 pm = &newMap
36 updateLock.Unlock()
37 }
38
39 func update(ptrMap *map[string]string) {
40 (*ptrMap)["test"] = "test"
41 }
Мне кажется, карта создана в функции handle
, которая переданный в функцию update
для изменения в строке 40, отличается от карты, считываемой в строке 24. Замена указателя происходит после завершения обновления, так почему существует такая гонка данных:
==================
WARNING: DATA RACE
Read at 0x00c000070030 by goroutine 7:
runtime.mapaccess2_faststr()
/home/vagrant/.go/src/runtime/map_faststr.go:107 +0x0
main.main.func2()
/vagrant/go_projects/src/learn/race/main.go:24 +0xd1
Previous write at 0x00c000070030 by goroutine 6:
runtime.mapassign_faststr()
/home/vagrant/.go/src/runtime/map_faststr.go:202 +0x0
main.update()
/vagrant/go_projects/src/learn/race/main.go:40 +0xba
main.handle()
/vagrant/go_projects/src/learn/race/main.go:33 +0x7f
main.main.func1()
/vagrant/go_projects/src/learn/race/main.go:18 +0x5f
Goroutine 7 (running) created at:
main.main()
/vagrant/go_projects/src/learn/race/main.go:21 +0xc4
Goroutine 6 (finished) created at:
main.main()
/vagrant/go_projects/src/learn/race/main.go:16 +0xa2
==================
PS Когда строки 23 и 26 не прокомментированы, гонка исчезает.