Concurrent Map
背景
map是平时项目中经常用到的数据类型,但是如果多个协程去读写同一个map时,为了不发生数据错误,经常去将其和锁封装成一个新的map。像以下两种示例。
type LockMap struct {
m map[interface{}]interface{}
lock sync.Mutex
}
type RwLockMap struct {
m map[interface{}]interface{}
lock sync.RWMutex
}
LockMap中,每次去读或者写时,都会调用Mutex去把map锁住。
RwLockMap中,如果程序中读较多,写较少的情况下,性能会比LockMap高很多,因为读的时候是可以多个协程一起读的。但是如果写较多时,性能可能与LockMap差不多。
这是我们不想看到的,我们想的是,随便读随便写,并且不会发生数据错误。go语言中有一个sync.Map.
sync.Map会有两块区域,一个是只读,一个是可读可写,其中可读可写的区域也是有一个锁的。每次操作时,会先去只读区域中寻找,只读区域未找到的时候触发miss,然后才会去可读可写区域寻找。很显然,最糟糕的情况下比LockMap性能更低,因为比LockMap多一次查找的动作。sync.Map也是适合读多写少的情况。