go語言學習--map的並發

來源:互聯網
上載者:User

標籤:must   faq   exec   ready   其他   cas   when   put   雜湊   

go提供了一種叫map的資料結構,可以翻譯成映射,對應於其他語言的字典、雜湊表。藉助map,可以定義一個鍵和值,然後可以從map中擷取、設定和刪除這個值,尤其適合資料尋找的情境。但是map的使用有一定的限制,如果是在單個協程中讀寫map,那麼不會存在什麼問題,如果是多個協程並發訪問一個map,有可能會導致程式退出,並列印下面錯誤資訊:

fatal error: concurrent map read and map write

上面的這個錯誤不是每次都會遇到的,如果並發訪問的協程數不大,遇到的可能性就更小了。例如下面的程式:

 1 package main 2  3 func main() { 4     Map := make(map[int]int) 5  6     for i := 0; i < 10; i++ { 7         go writeMap(Map, i, i) 8         go readMap(Map, i) 9     }10 11 }12 13 func readMap(Map map[int]int, key int) int {14     return Map[key]15 }16 17 func writeMap(Map map[int]int, key int, value int) {18     Map[key] = value19 }

只迴圈了10次,產生了20個協程並發訪問map,程式基本不會出錯,但是如果將迴圈次數變大,比如10萬,運行下面程式基本每次都會出錯:

 1 package main 2  3 func main() { 4     Map := make(map[int]int) 5  6     for i := 0; i < 100000; i++ { 7         go writeMap(Map, i, i) 8         go readMap(Map, i) 9     }10 11 }12 13 func readMap(Map map[int]int, key int) int {14     return Map[key]15 }16 17 func writeMap(Map map[int]int, key int, value int) {18     Map[key] = value19 }

go官方部落格有如下說明:

Maps are not safe for concurrent use: it‘s not defined what happens when you read and write to them simultaneously. If you need to read from and write to a map from concurrently executing goroutines, the accesses must be mediated by some kind of synchronization mechanism. One common way to protect maps is with sync.RWMutex.

go FAQ解釋如下:

After long discussion it was decided that the typical use of maps did not require safe access from multiple goroutines, and in those cases where it did, the map was probably part of some larger data structure or computation that was already synchronized. Therefore requiring that all map operations grab a mutex would slow down most programs and add safety to few. This was not an easy decision, however, since it means uncontrolled map access can crash the program.

大致意思就是說,並發訪問map是不安全的,會出現未定義行為,導致程式退出。所以如果希望在多協程中並發訪問map,必須提供某種同步機制,一般情況下通過讀寫鎖sync.RWMutex實現對map的並發存取控制,將map和sync.RWMutex封裝一下,可以實現對map的安全並發訪問,範例程式碼如下:

 1 package main 2  3 import "sync" 4  5 type SafeMap struct { 6     sync.RWMutex 7     Map map[int]int 8 } 9 10 func main() {11     safeMap := newSafeMap(10)12 13     for i := 0; i < 100000; i++ {14         go safeMap.writeMap(i, i)15         go safeMap.readMap(i)16     }17 18 }19 20 func newSafeMap(size int) *SafeMap {21     sm := new(SafeMap)22     sm.Map = make(map[int]int)23     return sm24 25 }26 27 func (sm *SafeMap) readMap(key int) int {28     sm.RLock()29     value := sm.Map[key]30     sm.RUnlock()31     return value32 }33 34 func (sm *SafeMap) writeMap(key int, value int) {35     sm.Lock()36     sm.Map[key] = value37     sm.Unlock()38 }

但是通過讀寫鎖控制map的並發訪問時,會導致一定的效能問題,不過能保證程式的安全運行,犧牲點效能問題是可以的。

參考

go官方部落格:https://blog.golang.org/go-maps-in-action

go FAQ:https://golang.org/doc/faq#atomic_maps



songleo
連結:https://www.jianshu.com/p/10a998089486

go語言學習--map的並發

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.