Go为何用tophash[0]判断哈希桶已完成迁移?
为什么Go的map用tophash[0]判断哈希桶是否已迁移?
先看源码里的判断函数:
func evacuated(b *bmap) bool { h := b.tophash[0] return h > emptyOne && h < minTopHash }
很多人会疑惑:tophash[0]不是对应桶里第一个元素的哈希高8位吗?怎么能用来判断整个桶的迁移状态?答案在于Go runtime对tophash数组的复用逻辑:
- tophash的双重身份:tophash数组主要用来存储每个元素哈希值的高8位,用于快速过滤不匹配的键,但runtime额外把
tophash[0]当成了整个桶的状态标记位。 - 迁移完成的标记规则:当一个哈希桶里的所有元素都被迁移到新桶后,runtime会把这个旧桶的
tophash[0]设为一个特殊值——这个值刚好落在emptyOne和minTopHash之间,而这个区间的数值永远不会被用作正常元素的tophash(正常元素的tophash会大于等于minTopHash)。 - 只查tophash[0]的原因:这是runtime内部的硬约定——只有整个桶的元素全迁移完,才会修改
tophash[0]的状态;反过来,只要tophash[0]处于这个特殊区间,就说明整个桶已经空了、完成迁移了。这么做的好处是不用遍历整个桶的tophash数组,扩容时能省不少时间。
说白了,这里的tophash[0]已经不是第一个元素的哈希标记了,而是被runtime拿来当整个桶的“迁移完成印章”用。
内容的提问来源于stack exchange,提问作者Alex Shang
相关产品推荐
相关产品推荐

