這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
一、map並發讀寫問題
如果map由多協程同時讀和寫就會出現 fatal error:concurrent map read and map write的錯誤
如下代碼很容易就出現map並發讀寫問題
func main(){c := make(map[string]int) go func() {//開一個協程寫map for j := 0; j < 1000000; j++ { c[fmt.Sprintf("%d", j)] = j } }() go func() { //開一個協程讀map for j := 0; j < 1000000; j++ { fmt.Println(c[fmt.Sprintf("%d",j)]) } }() time.Sleep(time.Second*20)}
多個協程同時寫也會出現fatal error: concurrent map writes的錯誤
如下代碼很容易出現map並發寫的問題
package mainimport ("fmt""time")func main() {c := make(map[string]int)for i := 0; i < 100; i++ {go func() { //開100個協程並發寫mapfor j := 0; j < 1000000; j++ {c[fmt.Sprintf("%d", j)] = j}}()}time.Sleep(time.Second * 20) //讓執行main函數的主協成等待20s,不然不會執行上面的並行作業}
二、出現問題的原因
因為map為參考型別,所以即使函數傳值調用,參數副本依然指向映射m, 所以多個goroutine並發寫同一個映射m, 寫過多線程程式的同學都知道,對於共用變數,資源,並發讀寫會產生競爭的, 故共用資源遭到破壞
三、解決方案
1、加鎖
(1)通用鎖
type Demo struct { Data map[string]string Lock sync.Mutex}func (d Demo) Get(k string) string{ d.Lock.Lock() defer d.Lock.UnLock() return d.Data[k]}func (d Demo) Set(k,v string) { d.Lock.Lock() defer d.Lock.UnLock() d.Data[k]=v}
(2)讀寫鎖
type Demo struct { Data map[string]string Lock sync.RwMutex}func (d Demo) Get(k string) string{ d.Lock.RLock() defer d.Lock.RUnlock() return d.Data[k]}func (d Demo) Set(k,v string) { d.Lock.Lock() defer d.Lock.UnLock() d.Data[k]=v}
2、利用channel序列化處理