sync.Map详解

sync.Map简述

简单来说,sync.Map是并发版本的map,golang自带的map在并发操作下会触发panic。sync.Map支持Load,Store, LoadOrStore,Range,Delete操作。其中Range支持在多goroutine下运作,能确保每个key最多被处理一次,但是无法保证遍历过程中实时同步其他goroutine的增删操作。

使用sync.Map

你真的需要sync.Map吗?

比起sync.Map如何使用,一个更重要的问题在于我们是否真的需要sync.Map。的确如我们之前所说,sync.Map支持并发而map不支持,但是我们可以很轻松的用RWMutex或者Mutex结合map来支持并发,而且比起sync.Map,这两种方案更好的支持类型安全,而且在绝大多数时候性能更优。一个简单的答案是,如果你不知道为什么需要sync.Map,那么很可能你不需要sync.Map

那么什么时候我们需要sync.Map呢?要解答这个问题,我们不妨回顾下sync.Map被提出的原因。简单来说,sync.Map被提出是因为google发现,RWLock配合map方案在高读取+多核cpu上表现不佳(具体可以翻看overview of sync map)。因此,snyc.Map就是为了改善多核高读取低写入时候的性能而引入。

具体来说,如果你的应用有以下的属性,那么可以考虑使用,否则更加建议使用RWMutex或者Mutex结合map的方案

  • 如果写入的key是稳定的(极少)
  • 如果不同goroutine对key的访问是不同的
如何更好地使用sync.Map

sync.Map有着非常简单的API,如果你需要存储新的键值对,你可以使用Store,如果你需要读取键值对,你可以使用Load;如果需要删除某个键值对,那么使用Delete;如果你需要遍历整个map,Range在那里等你。

但是我们如果观察sync.Map的API,我们会发现,为了考虑通用性,所有的key和value都是interface{},换言之,我们失去了类型检查提供的安全性而且被迫更多的使用类型断言。于是你面临着两种选择:在每次调用API后都小心翼翼地使用类型断言,你的代码里面出现无数的if v,ok=value.(xxType);!ok{};亦或者每一次都直接使用v.(xxType)直到你的进程在某些关键时刻宕机让你抓耳挠腮为止。那么我们还有第三种方案吗?庆幸的是,答案是有的,不过需要我们做出一些小小的努力。

如果你的map在使用的时候有明确类型,一个简单的思路是封装snyc.Map并且对外提供指定类型的LoadDeleteStore等等

type StringMap struct{
   
	m sync.Map
}
func (s *StringMap) Store(key,value string){
   
	s.m
  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值