衆所周知,golang的map是非協程安全的(go1.6版本之後,go1.6以前讀安全),而併發讀寫map的需求應該是很廣泛的。舉例以下:golang
package main import "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 main import ( "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 }) }