[zhuanlan.zhihu.com/p/540605192… 的实现原理可概括为: 1、过 read 和 dirty 两个字段将读写分离,读的数据存在只读字段,read 上,将最新写入的数据则存在 dirty 字段上 2、读取时会先查询 read,不存在再查询 dirty,写入时则只写入 dirty](zhuanlan.zhihu.com/p/540605192… 的实现原理可概括为: 1、过 read 和 dirty 两个字段将读写分离,读的数据存在只读字段,read 上,将最新写入的数据则存在 dirty 字段上 2、读取时会先查询 read,不存在再查询 dirty,写入时则只写入 dirty)
-
map是有序还是无序
当我们对map进行遍历时,每次遍历的输出的值顺序都可能不一样,顺序不固定。主要是因为map扩容(自动扩容和重新hash所有的key以便存储更多的数据)后,可能会将部分key移至新内存,即使没有扩容,map在遍历时加上随机的元素,将遍历 map 的顺序随机化。
写数据时,并没有单独维护键值对的顺序,成倍扩容迫使元素顺序变化,等量扩容并没有改变元素顺序。
其实就是Go的设计者们就对map增加了一种随机性,以确保开发者在使用map时不依赖于有序的这个特性。
-
map如何扩容的
map是如何扩容的:首先分成两种扩容。第一种是双倍扩容,因为负载因子太大,扩容后的桶数量是扩容前的两倍,而且key的地址会发生改变,会从旧的桶迁移到新的桶中;第二种是等量扩容,是因为负载因子太小了,浪费了空间,删除一些桶,使得key变得更紧凑。
-
map的并发安全
Go语言为什么不支持并发的读写,是一个频繁被提起的问题。Go 官方经过长时间的讨论,认为 map 适配的场景应该是简单的(不需要从多个 gorountine 中进行安全访问的),而不是为了小部分情况(并发访问),导致大部分程序付出锁的代价,因此决定了不支持。如果想在协程里用map有两种方法:一是自己加读写锁;二是用sync.Map底层也是加了一把锁。
-
map的负载因子为什么设置为6.5
首先介绍一下负载因子的概念:负载因子 = key数量/桶数量。说白了就是每个桶的平均key数量。当负载因子太多时,会导致冲突;当负载因子太小时,会导致大量的桶空间浪费。所以go开发者做了个实验,6.5为最佳平衡位置。