Golang - map并发不安全及解决方法

相关面试题

  1. map的底层实现原理

  2. 为什么遍历map是无序的?

  3. 如何实现有序遍历map?

  4. 为什么Go map是非线程安全的?

  5. 线程安全的map如何实现?

  6. Go sync.map 和原生 map 谁的性能好,为什么?

  7. 为什么 Go map 的负载因子是 6.5?

  8. 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的实现方式。

总结

  1. map是引用类型

  2. map遍历是无序的

  3. map是非线程安全的

  4. map的哈希冲突解决方式是链表法

  5. map的扩容不一定会新增空间,也有可能是只是做了内存整理

  6. map的迁移是逐步进行的,在每次赋值时,会做至少一次迁移工作

  7. map中删除key,有可能导致出现很多空的kv,这会导致迁移操作,如果可以避免,尽量避免


点赞(378)

评论列表共有 0 条评论

立即
投稿
返回
顶部