golang中map併發讀寫問題及解決方法

一、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併發寫的問題

func main(){

c := make(map[string]int)

for i := 0; i < 100; i++ {
        go func() {  //開100個協程併發寫map
              for 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

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章