我有以下代碼,並且我正在進行數據競賽。 Round函數定期檢查運行功能刪除地圖 的內容,當我讀到這裏:Is it safe to remove selected keys from Golang map within a range loop?Golang數據競賽,66退出狀態
從地圖上是安全的刪除數據,但我有數據爭
package main
import (
"fmt"
"sync"
"time"
)
type City struct {
ID string
}
type Map struct {
sync.RWMutex
Data map[string]City
}
var done = make(chan struct{})
func (m *Map) Round() {
for {
select {
case <-time.After(2 * time.Second):
for i, v := range m.Data {
fmt.Println("-----", v)
delete(m.Data, i)
}
case <-done:
println("bye")
break
}
}
}
func (m *Map) Add(id string, h City) {
m.Lock()
m.Data[id] = h
m.Unlock()
}
func main() {
m := Map{}
m.Data = make(map[string]City)
m.Data["Ottowa"] = City{"Canada"}
m.Data["London"] = City{"GB"}
m.Data["malafya"] = City{"malafya"}
go m.Round()
for i := 0; i < 4; i++ {
go func() {
time.Sleep(2 * time.Second)
go m.Add("uz", City{"CityMakon"})
go m.Add("uzb", City{"CityMakon"})
}()
}
time.Sleep(5 * time.Second)
done <- struct{}{}
}
輸出:
----- {Canada}
----- {GB}
----- {malafya}
==================
WARNING: DATA RACE
Write by goroutine 12:
runtime.mapassign1()
/usr/lib/golang/src/runtime/hashmap.go:411 +0x0
main.(*Map).Add()
/home/narkoz/elixir/round.go:37 +0xaa
Previous write by goroutine 6:
runtime.mapdelete()
/usr/lib/golang/src/runtime/hashmap.go:511 +0x0
main.(*Map).Round()
/home/narkoz/elixir/round.go:26 +0x3a9
Goroutine 12 (running) created at:
main.main.func1()
/home/narkoz/elixir/round.go:54 +0x8c
Goroutine 6 (running) created at:
main.main()
/home/narkoz/elixir/round.go:49 +0x2af
==================
----- {CityMakon}
----- {CityMakon}
Found 1 data race(s)
exit status 66
但是,當我將地圖的值類型更改爲int或字符串時,沒有數據競爭。
你推薦什麼解決方案?
我認爲這是影響結果的類型的巧合(但也許有人會更好地知道會回覆)。你需要鎖定地圖迭代,並在'Round()'中刪除。 – twotwotwo
謝謝,所以我用RLock和RUnlock封裝了範圍循環,這樣刪除了第二個數據競賽 – maksadbek
比賽檢測器告訴你_exactly_比賽發生在哪裏。你在沒有鎖的情況下調用'delete'。 – JimB