sync.map产生的原因
map是非线程安全的,当进行并发操作时容易产生意想不到的错误
sync.map的特点
1、sync.map 是线程安全的,读取,插入,删除也都保持着常数级的时间复杂度。
2、通过读写分离,降低锁时间来提高效率,适用于读多写少的场景。
3、Range 操作需要提供一个函数,参数是 k,v,返回值是一个布尔值:f func(key, value interface{}) bool。
4、调用 Load 或 LoadOrStore 函数时,如果在 read 中没有找到 key,则会将 misses 值原子地增加 1,当 misses 增加到和 dirty 的长度相等时,会将 dirty 提升为 read。以期减少“读 miss”。
5、新写入的 key 会保存到 dirty 中,如果这时 dirty 为 nil,就会先新创建一个 dirty,并将 read 中未被删除的元素拷贝到 dirty。
6、当 dirty 为 nil 的时候,read 就代表 map 所有的数据;当 dirty 不为 nil 的时候,dirty 才代表 map 所有的数据。
sync.map提供的操作方法及说明
// 通过键值获取对应的value值, 若存在,则ok为true,value值非空,否则ok为false,value值为空
func (m *Map) Load(key interface{}) (value interface{}, ok bool)
// 传入键值及value值,将数据存入map,无任何返回值
func (m *Map) Store(key, value interface{})
// 传入键值,对应map存在则删除,不存在则无任何操作
func (m *Map) Delete(key interface{})
// 传入键值及value值,如果 map 中存在这个 key,那么返回这个 key 对应的 value;否则,将 key-value 存入 map
func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool)
注:sync.map本身不带尺寸计算函数,所以在使用sync.map若是需要记录map的尺寸,那么最好自定义一个结构体,并添加size字段,另外sync.map声明即用,无需大费周章初始化操作,代码片段如下:
{
var smp sync.Map
// 数据写入
smp.Store("name", "小红")
}
下面附一篇解说很到位的文章,可参阅: