跳转到主内容
极星编程网:以代码为星,赴技术山海!

Go语言高并发删除sync.Map键值高负载效率压测评估

sync.Map.Delete在每秒超50次并发删除时性能通常低于加锁普通map,因其惰性删除、原子操作、内存屏障及dirty map提升开销大,且Delete与Store同属高成本写路径。 sync.Map.Delete 在每秒超 50 次并发删除时,性能通常比加锁的普通 map 更差,别硬扛高频删。 sync.Map.Delete 为什么一高并发就变慢 它不是“带锁的 map”,而是靠原子操作 + 内存屏障 + dirty map 提升来实现线程安全。Delete 并不真正释放内存,只是打标记(惰性删除);后续 Load 或 Range 才可能触发清理,带来不可预测延迟。更关键的是:每次 Delete 都要跳指针、做原子判断、检查 read/dirty 状态,写多时开销远超一次 mutex.Lock + delete + mutex.Unlock。 每秒写入(含 Store/Delete)超 50 次,sync.Map 吞吐常低于
sync.RWMutex
包裹的原生
map
大量 Delete 后紧接
Range
,会强制提升 dirty map,引发一次性扩容成本 热点 key 高频删除时,read map 的 entry 被反复标记为 deleted,导致后续 LoadOrStore 失效、Store 强制降级到 dirty,进一步放大开销 CompareAndDelete 是唯一推荐的条件删除方式(Go 1.20+) 如果你要“值匹配才删”,必须用
CompareAndDelete
,自己
Load
+
if
+
Delete
是竞态漏洞——中间可能被其他 goroutine 覆盖值。
CompareAndDelete(key, old)
返回
bool
,失败不 panic,必须显式判断
old
必须是同一地址或深度相等(结构体建议传指针);
nil
不支持比较,需先
Load
判断再调用 错误写法:
if v, ok := m.Load(k); ok && v == expected { m.Delete(k) }
—— 这段代码在并发下完全不原子 高频删除场景该换什么 sync.Map 本质只适合「创建一次、读一百次、删零次」的缓存类场景。真要每秒删几百 key,它就是错选。 go语言参考手册 中文CHM版 Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译 下载 立即学习 “ go语言免费学习笔记(深入) ”; 分片锁(sharded map):把大 map 拆成 32/64 个子 map,每个配独立
sync.Mutex
,key 哈希路由,吞吐通常高 20–40%
concurrent-map
(第三方库):提供
Remove
、
Count
、
Keys
等缺失能力,API 更贴近预期 重建实例:若删除是批量、周期性的(比如每分钟清空过期 session),不如定时新建
sync.Map{}
,旧实例让 GC 回收 避免误用:
Range
不是遍历工具,它是快照 + 全局锁,不能边删边遍历,也不能中断 最容易被忽略的一点:sync.Map 的 Delete 成本和 LoadOrStore 类似,都是“写路径”操作。很多人以为删得轻,其实它和 Store 一样触发 dirty map 升级逻辑。高频删的本质是高频写,而 sync.Map 就不是为这个设计的。

相关文章