SYNC MAP
map不支持并发读写,原因是:
- map底层的
hmap的flags做了状态标志,并发读写会panic - 底层控制的本质是防止扩容时,读map操作读到旧桶,写map正在做扩容迁移,将旧桶数据迁移到新桶,从而造成数据读取不正确
 
解决map并发问题
加锁(mutex)
加锁会导致同一时刻只能一个协程就操作map,性能比较差
sync map
map结构
1  | type Map struct {  | 

正常读写
正常读写操作read map,对map进行读取添加或修改操作
追加
比如追加的d=>D的kv:
先去read map查找有没有d,需要对dirty map上mutex锁,防止其他协程操作dirty map,然后在dirty map追加d,并将d.entry指向万能指针,由万能指针指向对应的值
同时将readmap的amended赋值为true

追加后的读
先去read map去看有没有该k,没有检查amended,如果为true则去查dirty map,并将misses++,当misses加到和dirty map kv数量相等时,提升dirty map为read map
sync map dirty提升流程:

当再一次追加新元素时会重建dirty map
追加后再删除
- 正常删除d:
正常删除主要操作read map,删除流程参考下图

 - 追加d后再次删除d:
先去read map去看有没有该k,没有检查amended,如果为true加锁,去dirty map查找,找到后删除k,并将pointer指向nil
然后将dirty map提升至read map,amended改为false
最后下次追加时重建dirty map
重建dirty map时,由于read map此时d指向nil,所以重建dirty map不会重建d
之后操作read map,并将d标记为expunged,提醒后面操作read map的d时,不用改为nil,直接从map当前buckets删除 
由于sync map只有在追加时才会操作
dirty map,所以可理解追加、读写分离
总结
- map在扩容时存在并发问题
 - sync map使用
dirty map和read map解决扩容问题 - 不存在扩容操作时直接读写
read map - 存在扩容操作时操作
dirty map