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

}

 

 

2、利用channel串行化處理


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM