1 回答

TA貢獻(xiàn)1802條經(jīng)驗(yàn) 獲得超5個(gè)贊
更新:
但是當(dāng)我將映射的值類型更改為 int 或 string 時(shí),沒有數(shù)據(jù)競爭。
我進(jìn)一步測試了你的代碼。將映射的值類型更改為 int 或 string 會(huì)繼續(xù)產(chǎn)生競爭條件。嘗試while在你的 shell 上循環(huán)運(yùn)行它,你會(huì)明白我的意思:
$ while true; do go run -race main.go; done
值類型之間不應(yīng)該有任何差異。
正如競態(tài)檢測器所報(bào)告的,有兩種不同的競態(tài)條件。第一場比賽(您已修復(fù))發(fā)生在i第 54 行的讀取 (of ) 和第i51 行的寫入 (to ) 之間。發(fā)生這種情況是因?yàn)槟?goroutine 閉包包含對(duì) 的引用,該引用由goroutine中的循環(huán)i更改. 您可以通過擺脫或傳遞給您的閉包來解決它,如下所示:formainprintln(">>", i)i
for i := 0; i < 4; i++ {
go func(index int) {
time.Sleep(2 * time.Second)
println(">>", index)
go m.Add("uz", City{"CityMakon"})
go m.Add("uzb", City{"CityMakon"})
}(i)
}
第二個(gè)競爭條件發(fā)生在第 37 行 ( m.Data[id] = h) 的賦值和第 25 行 ( ) 的刪除之間delete(m.Data, i)。競態(tài)檢測器將此標(biāo)記為競態(tài)條件,因?yàn)樗荒鼙WC您的代碼上的Happen Before約束。您可以通過以下任一方式解決此問題:
鎖定delete語句:
m.Lock()
delete(m.Data, i)
m.Unlock()
或者,將Round()方法中的兩種情況提取為兩種方法,覆蓋通道:
func (m *Map) Round() {
for i, v := range m.Data {
fmt.Println("-----", v)
delete(m.Data, i)
}
}
func (m *Map) Done() {
for range done {
println("bye")
break
}
}
func main() {
// ...
go Round()
go Done()
}
- 1 回答
- 0 關(guān)注
- 258 瀏覽
添加回答
舉報(bào)