直接并发读写原生map会panic,因非并发安全,运行时主动检测并终止程序;sync.map适用于高频读、低频写、键生命周期长的场景;sync.rwmutex保护普通map更可控且易调试。
为什么直接并发读写 map 会 panic
Go 的原生 map 不是并发安全的——只要有一个 goroutine 在写,其他 goroutine 就不能同时读或写,否则运行时会直接触发 fatal error: concurrent map read and map write。这不是概率性 bug,而是确定性崩溃,哪怕读多写少、写操作极少,也逃不掉。
根本原因在于 map 底层结构(如桶数组、扩容逻辑)在写入时可能重排内存,而读操作若恰好撞上中间状态,就会访问非法地址或读到损坏数据。Go 运行时主动检测并 panic,其实是种保护机制。
sync.Map 适合什么场景
sync.Map 是标准库提供的并发安全 map,但它不是万能替代品。它的设计目标很明确:**高频读 + 低频写 + 键生命周期长(不频繁增删)**。
- 读操作(
Load)几乎无锁,性能接近原生 map; - 写操作(
Store)在键已存在时很快,但首次写入或删除后再次写入,可能触发内部清理,有额外开销; - 不支持遍历(
Range是快照式回调,期间增删不影响当前遍历,但无法保证原子性); - 不支持获取长度(
len)、不支持类型断言以外的批量操作。
如果你需要频繁 range、统计总数、或写操作占比超过 20%,sync.Map 反而可能比加锁的普通 map 更慢。