4 回答

TA貢獻1155條經驗 獲得超0個贊
如果并發進程向全局變量寫入相同的值會怎樣?
數據競爭的結果是不確定的。
運行 Go 數據競爭檢測器。
參考:
在 Go 1.6 中,運行時添加了輕量級的、最大努力的映射并發濫用檢測。此版本改進了該檢測器,支持檢測同時寫入和遍歷映射的程序。
與往常一樣,如果一個 goroutine 正在寫入 map,則沒有其他 goroutine 應該同時讀?。òǖ┗驅懭?map。如果運行時檢測到這種情況,它會打印診斷并使程序崩潰。找出更多有關問題的最佳方法是在競爭檢測器下運行程序,這將更可靠地識別競爭并提供更多詳細信息。
例如,
package main
import "time"
var linksToVisit = map[string]bool{}
func main() {
someLink := "someLink"
go func() {
for {
linksToVisit[someLink] = true
}
}()
go func() {
for {
linksToVisit[someLink] = true
}
}()
time.Sleep(100 * time.Millisecond)
}
輸出:
$ go run racer.go
fatal error: concurrent map writes
$
$ go run -race racer.go
==================
WARNING: DATA RACE
Write at 0x00c000078060 by goroutine 6:
runtime.mapassign_faststr()
/home/peter/go/src/runtime/map_faststr.go:190 +0x0
main.main.func2()
/home/peter/gopath/src/racer.go:16 +0x6a
Previous write at 0x00c000078060 by goroutine 5:
runtime.mapassign_faststr()
/home/peter/go/src/runtime/map_faststr.go:190 +0x0
main.main.func1()
/home/peter/gopath/src/racer.go:11 +0x6a
Goroutine 6 (running) created at:
main.main()
/home/peter/gopath/src/racer.go:14 +0x88
Goroutine 5 (running) created at:
main.main()
/home/peter/gopath/src/racer.go:9 +0x5b
==================
fatal error: concurrent map writes
$

TA貢獻1893條經驗 獲得超10個贊
如果您使用多個 go 例程同時更改相同的值,則最好使用鎖。由于當另一個函數正在更改相同值時,無論何時都使用互斥鎖和鎖來保護值不被訪問,就像在訪問同一個表時寫入數據庫表一樣。
對于您關于使用具有不同鍵的地圖的問題,在 Go 中并不可取,因為:
map 的典型使用不需要從多個 goroutine 進行安全訪問,在需要的情況下,map 可能是某個更大的數據結構或已經同步的計算的一部分。因此,要求所有映射操作都獲取一個互斥量會減慢大多數程序的速度并增加少數程序的安全性。
只有在發生更新時,地圖訪問才是不安全的。只要所有 goroutines 都只是讀取——查找地圖中的元素,包括使用 for range 循環遍歷它——而不是通過分配給元素或進行刪除來更改地圖,它們就可以安全地同時訪問地圖而無需同步。
因此,不建議更新地圖。有關詳細信息,請查看關于為什么映射操作未定義為原子的常見問題解答。
還注意到,如果你真的想去 for 應該有一種方法來同步它們。
映射對于并發使用是不安全的:它沒有定義當你同時讀取和寫入它們時會發生什么。如果您需要從并發執行的 goroutine 讀取和寫入映射,則訪問必須通過某種同步機制進行調解。保護地圖的一種常見方法是使用 sync.RWMutex。
- 4 回答
- 0 關注
- 155 瀏覽
添加回答
舉報