新版 sync.Map 的变化

639 阅读1分钟

在 Go 1.24 里,sync.Map 的内部实现不再是“只读快照 + 脏表”那套组合拳,而是切到了一个并发哈希前缀树(HashTrieMap)上,这套树形结构最先在 unique 包里测试,后来直接拿来当底层实现,读写都在节点级别并发搞定,锁冲突少了,更自然;如果真遇到兼容问题,还能通过 GOEXPERIMENT=nosynchashtriemap 回退到旧版 。


旧版 sync.Map

  1. 老版 sync.Map 核心由两个 map 组成:一个只读快照(readOnly),一个写时用的“脏表”(dirty) 。
  2. 读操作先看只读快照,命中就原子返回;若快照没命中且标记了脏表,再加锁去脏表里找,必要时把脏表整体合并到快照里 。
  3. 写操作都先落到脏表,只有当“未命中”次数攒够了,才触发脏表升级成新快照 。

新版 sync.Map

  1. Go 1.24 直接把底层换成 并发哈希前缀树HashTrieMap),节点上用原子操作和小范围锁,读写都在树节点级别并行,不再分快照/脏表两块 。
  2. 新结构抛弃了双表设计,用树形哈希前缀把键分层存储,自动并发,对写冲突友好 。
  3. 如果有兼容顾虑,设置 GOEXPERIMENT=nosynchashtriemap 就能退回到老版实现 。
  4. 由于接口没变,老代码直接跑在新实现上就能享受底层升级,无需任何改动 。

核心变化

  • 旧版:双 map 设计,读走快照、写进脏表,加锁+升级;
  • 新版:HashTrieMap 树形结构,节点级原子操作/小范围锁,读写都并行;
  • 兼容兜底:环境变量一键切回旧实现;

性能对比

image.png