一、map并发读写问题
如果map由多协程同时读和写就会出现fatalerror:concurrentmapreadandmapwrite的错误
如下代码很容易就出现map并发读写问题
funcmain(){
c:=make(map[string]int)
Gofunc(){//开一个协程写map
forj:=0;j<1000000;j++{
c[fmt.Sprintf(“%d”,j)]=j
}
}()
gofunc(){//开一个协程读map
forj:=0;j<1000000;j++{
fmt.Println(c[fmt.Sprintf(“%d”,j)])
}
}()
time.Sleep(time.Second*20)
}
多个协程同时写也会出现fatalerror:concurrentmapwrites的错误
如下代码很容易出现map并发写的问题
func main(){
c:=make(map[string]int)
fori:=0;i<100;i++{
gofunc(){ //开100个协程并发写map
forj:=0;j<1000000;j++{
c[fmt.Sprintf(“%d”,j)]=j
}
}()
}
time.Sleep(time.Second*20)//让执行main函数的主协成等待20s,不然不会执行上面的并发操作
}
二、出现问题的原因
因为map为引用类型,所以即使函数传值调用,参数副本依然指向映射m,所以多个goroutine并发写同一个映射m,写过多线程程序的同学都知道,对于共享变量,资源,并发读写会产生竞争的,故共享资源遭到破坏
三、解决方法
1、加锁
(1)通用锁
typeDemostruct{
Datamap[string]string
Locksync.Mutex
}
func(dDemo)Get(kstring)string{
d.Lock.Lock()
deferd.Lock.UnLock()
returnd.Data[k]
}
func(dDemo)Set(k,vstring){
d.Lock.Lock()
deferd.Lock.UnLock()
d.Data[k]=v
}
(2)读写锁
type MapTplResCode struct {
Data map[ string] int
Lock *sync.RWMutex
}
func (d MapTplResCode) Get(k string) ( int, bool) {
d.Lock. RLock()
defer d.Lock. RUnlock()
if v, ok := d.Data[k]; ok {
return v, true
}
return 0, false
}
func (d MapTplResCode) Set(k string, v int) {
d.Lock. Lock()
defer d.Lock. Unlock()
d.Data[k] = v
}
func (d MapTplResCode) Init() {
d.Lock. Lock()
defer d.Lock. Unlock()
//d.Data = make(map[string]int)
for key, _ := range d.Data {
delete(d.Data, key)
}
}
2、利用channel串行化处理