眾所周知,golang的map是非協程安全的(go1.6版本以後,go1.6之前讀安全),而並發讀寫map的需求應該是很普遍的。舉例如下:
package mainimport "fmt"func main() { a := make(map[int]bool, 0) for i:=0;i<100;i++{ go func() { for i := 0; i < 20000; i++ { a[i] = false fmt.Printf("%v %v\n",i,a[i]) } }() }}
運行報錯:
fatal error: concurrent map writes
1.9版本之前,官方提供的解決方案是自己封裝個帶同步鎖的struct。例如:
package mainimport ( "fmt" "sync")type SafeMap struct{ sync.RWMutex data map[int]int}func main() { a := SafeMap{data: make(map[int]int)} for i:=0;i<100;i++{ go func() { for j := 0; j < 20000; j++ { a.Lock() a.data[j] = i fmt.Printf("%v %v\n", i, j) a.Unlock() } }() }}
1.9版本以後,sync包引入了sync.Map,效能比起之前的解決方案有比較大的提升:
package main import ( "fmt" "sync" ) func main() { a := new(sync.Map) wg := new(sync.WaitGroup) wg.Add(100) for i:=0;i<100;i++{ go func() { for j := 0; j < 100; j++ { a.Store(i, j) } wg.Done() }() } wg.Wait() a.Range(func(key, value interface{}) bool { fmt.Printf("%v %v\n", key, value) return true }) }