Golang - map并发不安全及解决方法
相关面试题
map的底层实现原理
为什么遍历map是无序的?
如何实现有序遍历map?
为什么Go map是非线程安全的?
线程安全的map如何实现?
Go sync.map 和原生 map 谁的性能好,为什么?
为什么 Go map 的负载因子是 6.5?
map扩容策略是什么?
1、map默认是并发不安全的,原因如下:
1)、 典型使用场景:map 的典型使用场景是不须要从多个 goroutine 中进行安全访问;
2)、非典型场景(须要原子操做):map 多是一些更大的数据结构或已经同步的计算的一部分;
3)、性能场景考虑:如果只是为少数程序增长安全性,致使 map 全部的操做都要处理 mutex,将会下降大多数程序的性能。
Go 官方团队在经过了长时间的讨论后,认为 Go map 更应适配典型使用场景(不需要从多个 goroutine 中进行安全访问),而不是为了小部分情况(并发访问),导致大部分程序付出加锁代价(性能),所以决定了不支持并发安全。
2、如果想实现map线程安全,有两种方式:
方式一:使用读写锁 map
+ sync.RWMutex
方式二:使用golang提供的 sync.Map
sync.Map是用读写分离实现的,其思想是空间换时间。和map+RWLock的实现方式相比,它做了一些优化:可以无锁访问read map,而且会优先操作read map,倘若只操作read map就可以满足要求(增删改查遍历),那就不用去操作write map(它的读写都要加锁),所以在某些特定场景中它发生锁竞争的频率会远远小于map+RWLock的实现方式。
总结
map是引用类型
map遍历是无序的
map是非线程安全的
map的哈希冲突解决方式是链表法
map的扩容不一定会新增空间,也有可能是只是做了内存整理
map的迁移是逐步进行的,在每次赋值时,会做至少一次迁移工作
map中删除key,有可能导致出现很多空的kv,这会导致迁移操作,如果可以避免,尽量避免
发表评论 取消回复