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

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

Golang 映射對于并發讀/寫操作的安全性如何?

Golang 映射對于并發讀/寫操作的安全性如何?

Go
料青山看我應如是 2021-12-27 15:39:40
根據 Go 博客,映射對于并發使用是不安全的:它沒有定義當您同時讀取和寫入它們時會發生什么。如果您需要從并發執行的 goroutine 中讀取和寫入映射,則訪問必須通過某種同步機制進行調解。(來源:https : //blog.golang.org/go-maps-in-action)任何人都可以詳細說明這一點嗎?跨例程的并發讀取操作似乎是允許的,但如果嘗試讀取和寫入同一個鍵,并發讀/寫操作可能會產生競爭條件。在某些情況下,這最后的風險可以降低嗎?例如:函數A生成k并設置m[k]=0。這是 A 寫入映射 m 的唯一一次。已知 k 不在 m 中。A 將 k 傳遞給同時運行的函數 BA 然后讀取 m[k]。如果 m[k]==0,則等待,僅當 m[k]!=0 時繼續B 在地圖中尋找 k。如果找到,B 將 m[k] 設置為某個正整數。如果不是,它會等到 k 在 m 中。這不是代碼(顯然),但我認為它顯示了一種情況的輪廓,即使 A 和 B 都嘗試訪問 m 也不會有競爭條件,或者如果存在競爭條件也沒關系,因為額外的約束。
查看完整描述

2 回答

?
開滿天機

TA貢獻1786條經驗 獲得超13個贊

Golang 1.6之前并發讀可以,并發寫不行,寫并發讀可以。從 Golang 1.6 開始,map 在寫入時無法讀取。所以在 Golang 1.6 之后,并發訪問映射應該是這樣的:


package main


import (

    "sync"

    "time"

)


var m = map[string]int{"a": 1}

var lock = sync.RWMutex{}


func main() {

    go Read()

    time.Sleep(1 * time.Second)

    go Write()

    time.Sleep(1 * time.Minute)

}


func Read() {

    for {

        read()

    }

}


func Write() {

    for {

        write()

    }

}


func read() {

    lock.RLock()

    defer lock.RUnlock()

    _ = m["a"]

}


func write() {

    lock.Lock()

    defer lock.Unlock()

    m["b"] = 2

}

或者你會得到以下錯誤:

http://img1.sycdn.imooc.com//61c96dd90001bc9906470367.jpg

添加:


您可以通過使用檢測種族 go run -race race.go


更改read功能:


func read() {

    // lock.RLock()

    // defer lock.RUnlock()

    _ = m["a"]

}

http://img1.sycdn.imooc.com//61c96de400011def08720531.jpg

另一種選擇:

眾所周知,map是由桶實現的,sync.RWMutex會鎖定所有的桶。concurrent-map用于fnv32對鍵進行分片,每個存儲桶使用一個sync.RWMutex.


查看完整回答
反對 回復 2021-12-27
?
森欄

TA貢獻1810條經驗 獲得超5個贊

Go 1.6 發行說明

運行時添加了輕量級、盡力而為的并發誤用映射檢測。與往常一樣,如果一個 goroutine 正在寫入地圖,則沒有其他 goroutine 應該同時讀取或寫入地圖。如果運行時檢測到這種情況,它會打印診斷信息并使程序崩潰。找出更多問題的最好方法是在比賽檢測器下運行程序,這將更可靠地識別比賽并提供更多細節。

映射是復雜的、自重組的數據結構。并發讀寫訪問未定義。

沒有代碼,沒有什么可說的。


查看完整回答
反對 回復 2021-12-27
  • 2 回答
  • 0 關注
  • 190 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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