go中普通map和sync.map的区别小结
目录
- 1. 普通map的特点
- 2.sync.Map的特点
- 3. 举个对比例子
- 4. 面试回答
1. 普通map的特点
Go 内置的 map
是非并发安全的:
- 在单协程里读写没问题;
- 多协程同时写会触发
fatal error: concurrent map writes
; - 多协程并发读写需要自己加锁(如
sync.RWMutex
)。
源码层面(runtime/map.g编程o
):
map
内部通过hmap
结构体存储桶(buckets)管理数据;- 设计目标是高性能单线程;
- 并没有加锁逻辑。
2.sync.Map的特点
Go 在 1.9+ 引入了 sync.Map
,为高并发场景做了专门优化。
- 并发安全,内部已经封装了锁;
- 针对读多写少的场景做了特别优化(类似“读写分离”)。
源码层面(sync/map.go
):
type Map struct { mu Mutex // 写操作用的锁 read atomic.Value // 存储只读部分,原子读 dirty map[any]*entry // 可写部分,写时更新 misses int // 记录从 read 读取失败的次数 }
核心机制:
双 map 设计:
read
(只读,atomic.Value):无锁读,性能高;dirty
(写缓冲www.devze.com,受锁保护):存储新增/修改的数据;
写时迁移策略:当
read
中 miss 次数过多,会把dirty
提升为read
;保证读快写慢的同时,整体高并发安全。
通过read和dirty
分别存储读写
状态,以空间换时间的策略,去减少锁冲突。
3. 举个对比例子
// 普通 map + 锁 var m = make(map[string]int) var mu sync.RWMutex func safeWrite(k string, v编程客栈 int) { mu.Lock() defer mu.Unlock() m[k] = v } func safeRead(k string) (int, bophpol) { mu.RLock() defer mu.RUnlock() v, ok := m[k] return v, ok }
和 sync.Map
相比:
- 普通
map+RWMutex
:写性能更好,适合频繁写; sync.Map
:读性能更好,适合读多写少。
4. 面试回答
普通 map 是非并发安全的,需要开发者手动用 sync.RWMutex
保证线程安全。
dirty
提升为 read
。适用场景不同:
sync.Map
:读多写少,典型场景如缓存、配置表;map+RWMutex
:写多的场景更优。
到此这篇关于go中普通map和sync.map的区别小结的文章就介绍到这了,更多相关go中普通map和sync.map内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论