相关面试题

  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默认是并发不安全的,原因如下:

  Go 官方团队在经过了长时间的讨论后,认为 Go map 更应适配典型使用场景(不需要从多个 goroutine 中进行安全访问),而不是为了小部分情况(并发访问),导致大部分程序付出加锁代价(性能),所以决定了不支持并发安全。

2、如果想实现map线程安全,有两种方式:

mapsync.RWMutex
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,这会导致迁移操作,如果可以避免,尽量避免