sync.Map
位于sync包中,主要解决map的线程安全的问题,适用于读多写少的场景。
sync.Map的原理
内部持有俩个map,一个是read,类型是atomic.Value实际类型是【map[interface{}]entry】,一个是dirty类型是map【[interface{}]entry】。
其中read主要解决无数据竞争的情况下数据的快速访问,它通过cas进行快速的读写操作;一旦出现数据的竞争,就会用到dirty,dirty里面保存read里所有非nil的值【通过状态来表示unexpunged】,当出现竞争后数据会写到dirty而不是read中。
数据的访问路径大致是:
- 读,先从read里找,read里没有,去dirty里找,如果miss过一定的阈值【dirty的长度】时候,将dirty和read交换,交换后dirty置为nil;
写,先判断key是否存在,如果存在且不为expunaged,先通过cas写快速返回,否则有如下分支:
- 如果key是expunaged,说明key之前被删除了,但是dirty没有,unexpunaged之后同步修改read和dirty
- 如果key不存在于read,但是存在于dirty修改dirty
- 如果key不存在与read和dirty,初始化dirty【如果需要】,数据写入dirty
因为数据在并发写的时候一旦发生竞争还是会用到锁,并发写的时候的锁是不可避免的。所以sync.Map适用于读多写少数据冲突不那么复杂的场景
sync.Map的源码分析
结构体分析
1 | type Map struct { |
Store
1 | func (m *Map) Store(key, value interface{}) { |
Load
1 | func (m *Map) Load(key interface{}) (value interface{}, ok bool) { |
Delete
1 | func (m *Map) Delete(key interface{}) { |