golang中map的三个结论:多协程同时只写入,会发生 concurrent map write 异常,必须加锁
多协程同时写入读取,写入加锁,读取不加,不会异常,只是不确保读取的数据是否脏
多协程同时只读取,加锁数据干净,不加锁数据可能脏
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
var m = make(map[string]*int,0)
var l = & sync.RWMutex{}
var a = 5
m ["a"] = &a
var wg = sync.WaitGroup{}
for i:=0;i<10000;i++ {
wg.Add(1)
go func(wg *sync.WaitGroup, m *map[string]*int,l *sync.RWMutex) {
defer wg.Done()
writeM(m,l)
}(&wg, &m, l)
}
for i:=0;i<10000;i++ {
wg.Add(1)
go func(wg *sync.WaitGroup, m *map[string]*int,l *sync.RWMutex) {
defer wg.Done()
readM(m,l)
}(&wg, &m, l)
}
for i:=0;i<10000;i++ {
wg.Add(1)
go func(wg *sync.WaitGroup, m *map[string]*int,l *sync.RWMutex) {
defer wg.Done()
changeA(&a)
}(&wg, &m, l)
}
wg.Wait()
}
func readM(m *map[string]*int,l *sync.RWMutex){
l.RLock()
defer l.RUnlock()
a := (*m)["a"]
fmt.Println(a)
}
func writeM(m *map[string]*int,l *sync.RWMutex) {
l.Lock()
defer l.Unlock()
var tmp = 7
(*m)["a"] = &tmp
}
func changeA(a *int){
*a++
}
如代码所示,1万协程读,1万协程写,1万协程无锁修改其value指针对象的值,并不会因为造成读写崩溃。
map的读写场景:
var m map[string]*string
tmp := "3"
// 写
go func(){
m["5"] = &tmp
}
// 读
go func(){
_ = m["5"]
}()
// 此不属于写,是map安全的操作,无须加map 锁
*tmp = "4"