執行以下程式會go run.產生致命錯誤,例如
fatal error: concurrent map writes
goroutine 103 [running]:
...
運行時檢測到 上的惡意訪問map,但未檢測到slice
為什么會這樣?
這是我寫的程式:
package main
import (
"time"
)
func main() {
m := map[string]int{"a":1}
s := []int{1}
for i := 0; i < 1000; i {
go func() {
m["a"] = i
s[0] = i
}()
}
time.Sleep(3 * time.Second)
}
uj5u.com熱心網友回復:
地圖中的內置種族檢測器是唾手可得的果實。該功能使用的備用位在映射頭進行存盤。該功能的 CPU 成本非常低。hashWriting在runtime/map.go 中搜索以查看實作。
切片的內置競爭檢測器將導致記憶體開銷、CPU 開銷或兩者兼而有之,因為每個切片元素都是記憶體模型中的一個單獨變數。在競爭檢測器實作中,每個切片元素沒有備用位。
使用Go Race Detector檢測所有資料競爭,包括切片元素上的競爭。Go Race Detector 檢測代碼以記錄和檢測記憶體的訪問方式。
uj5u.com熱心網友回復:
首先,假設我們談論的是修改切片的內容(而不是切片定義本身),只要您不同時修改相同的確切元素,切片對于并發讀/寫是安全的。這意味著要準確檢測不正確的并發訪問,您需要在每個元素的基礎上對其進行跟蹤。這將是過多的記憶體開銷。
其次,切片旨在作為對陣列的薄抽象,陣列本身是對直接記憶體訪問(在受限范圍內)的薄抽象。也就是說,操作預計會非常快。在語言級別檢測不正確的并發訪問將是一個過多的處理開銷。
在映射的情況下,首先使用資料結構的記憶體和處理開銷足以使運行這種并發檢查的成本相形見絀。因此,內置這種方便的安全功能被認為是一種積極的態度。
您確實可以使用 Go 的競爭檢測器檢測切片上的資料競爭,但如檔案所述:
競爭檢測的成本因程式而異,但對于典型的程式,記憶體使用量可能會增加 5-10 倍,執行時間會增加 2-20 倍。
uj5u.com熱心網友回復:
即使未啟用競態檢測器,運行時也足以在發生惡意訪問時警告最終用戶。
如果您在啟用了競爭檢測器的情況下執行該程式,go run -race .您會得到這樣的輸出
$ go run -race .
...
==================
WARNING: DATA RACE
Write at 0x00c000124000 by goroutine 8:
main.main.func1()
/home/mh-cbon/gow/src/test/d/dr/main.go:14 0xd7
Previous write at 0x00c000124000 by goroutine 6:
main.main.func1()
/home/mh-cbon/gow/src/test/d/dr/main.go:14 0xd7
Goroutine 8 (running) created at:
main.main()
/home/mh-cbon/gow/src/test/d/dr/main.go:12 0x12a
Goroutine 6 (finished) created at:
main.main()
/home/mh-cbon/gow/src/test/d/dr/main.go:12 0x12a
==================
Found 4 data race(s)
exit status 66
這意味著在第 14 ( s[0] = i) 行,并發訪問從第 12 行開始go func() {。
在https://go.dev/blog/race-detector閱讀更多關于比賽檢測器的資訊
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/312980.html
上一篇:Python迭代和創建嵌套字典
