map不是並發安全的 , 當有多個並發的groutine讀寫同一個map時
會出現panic錯誤
concurrent map writes
例如下面的代碼會出現這個錯誤:
var mMap map[int]int func TestMyMap(t *testing.T) { mMap = make(map[int]int) for i := 0; i < 5000; i++ { go func() { mMap[i] = i }() go readMap(i) } } func readMap(i int) int { return mMap[i] }
解決這個錯誤可以有多種方式 , 現在采取讀寫鎖的方式 ,
並發訪問map是不安全的,會出現未定義行為,導致程序退出。所以如果希望在多協程中並發訪問map,必須提供某種同步機制,一般情況下通過讀寫鎖sync.RWMutex實現對map的並發訪問控制,將map和sync.RWMutex封裝一下,可以實現對map的安全並發訪問
改造后的代碼
type SMap struct { sync.RWMutex Map map[int]int } func (l *SMap) readMap(key int) (int, bool) { l.RLock() value, ok := l.Map[key] l.RUnlock() return value, ok } func (l *SMap) writeMap(key int, value int) { l.Lock() l.Map[key] = value l.Unlock() } var mMap *SMap func TestMyMap(t *testing.T) { mMap = &SMap{ Map: make(map[int]int), } for i := 0; i < 5000; i++ { go func() { mMap.writeMap(i, i) }() go readMap(i) } } func readMap(i int) (int, bool) { return mMap.readMap(i) }
有這三種方式:
1.使用channel
2.使用sync.map
3.使用map但必須進行加鎖