亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如果并發進程向全局變量寫入相同的值會怎樣?

如果并發進程向全局變量寫入相同的值會怎樣?

Go
慕碼人2483693 2023-03-21 15:45:42
我只是想知道是否有可能由于同時將相同的值寫入全局變量而導致損壞。我的大腦告訴我這沒有任何問題,因為它只是內存中的一個位置,但我認為我應該仔細檢查這個假設。我有寫入全局地圖的并發進程var linksToVisit map[string]bool。該地圖實際上是在跟蹤網站上的哪些鏈接需要進一步抓取。然而,并發進程可能在它們各自的頁面上有相同的鏈接,因此每個進程都會將相同的鏈接標記為true并發。在這種情況下不使用鎖沒有錯吧?注意:我從不將值改回,false所以要么鍵存在并且它的值為真,要么它不存在。IEvar linksToVisit = map[string]bool{}... // somewhere later a goroutine finds a link and marks it as true// it is never marked as false anywherelinksToVisit[someLink] = true 
查看完整描述

4 回答

?
白衣非少年

TA貢獻1155條經驗 獲得超0個贊

如果并發進程向全局變量寫入相同的值會怎樣?

數據競爭的結果是不確定的。

運行 Go 數據競爭檢測器。

參考:

維基百科:比賽條件

良性數據競賽:可能出現什么問題?

Go 博客:介紹 Go 競速檢測器

Go:數據競爭檢測器


Go 1.8 發行說明

并發映射濫用

在 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


$


查看完整回答
反對 回復 2023-03-21
?
白豬掌柜的

TA貢獻1893條經驗 獲得超10個贊

如果您使用多個 go 例程同時更改相同的值,則最好使用鎖。由于當另一個函數正在更改相同值時,無論何時都使用互斥鎖和鎖來保護值不被訪問,就像在訪問同一個表時寫入數據庫表一樣。

對于您關于使用具有不同鍵的地圖的問題,在 Go 中并不可取,因為:

map 的典型使用不需要從多個 goroutine 進行安全訪問,在需要的情況下,map 可能是某個更大的數據結構或已經同步的計算的一部分。因此,要求所有映射操作都獲取一個互斥量會減慢大多數程序的速度并增加少數程序的安全性。

只有在發生更新時,地圖訪問才是不安全的。只要所有 goroutines 都只是讀取——查找地圖中的元素,包括使用 for range 循環遍歷它——而不是通過分配給元素或進行刪除來更改地圖,它們就可以安全地同時訪問地圖而無需同步。

因此,不建議更新地圖。有關詳細信息,請查看關于為什么映射操作未定義為原子的常見問題解答。

還注意到,如果你真的想去 for 應該有一種方法來同步它們。

映射對于并發使用是不安全的:它沒有定義當你同時讀取和寫入它們時會發生什么。如果您需要從并發執行的 goroutine 讀取和寫入映射,則訪問必須通過某種同步機制進行調解。保護地圖的一種常見方法是使用 sync.RWMutex。


查看完整回答
反對 回復 2023-03-21
?
ibeautiful

TA貢獻1993條經驗 獲得超6個贊

并發映射寫入不正常,因此您很可能會遇到致命錯誤。所以我認為應該使用鎖



查看完整回答
反對 回復 2023-03-21
?
侃侃爾雅

TA貢獻1801條經驗 獲得超16個贊

從 Go 1.6 開始,同時寫入 map 將導致panic. 使用 async.Map同步訪問。

查看映射值分配實現: https://github.com/golang/go/blob/fe8a0d12b14108cbe2408b417afcaab722b0727c/src/runtime/hashmap.go#L519


查看完整回答
反對 回復 2023-03-21
  • 4 回答
  • 0 關注
  • 155 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號