1. 程式人生 > >golang中map並發讀寫問題及解決方法

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

傳值調用 .data 協程 資源 線程 string 錯誤 int println

一、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串行化處理

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