golang sync.Map实现原理
嘻嘻发布于2022-08-27
最后更新于2022年8月3日
浏览sync.Map 的实现原理可概括为: 通过 read 和 dirty 两个字段将读写分离,读的数据存在只读字段 read 上,将最新写入的数据则存在 dirty 字段上 读取时会先查询 read,不存在再查询 dirty,写入时则只写入 dirty,当达到同步的条件时,将dirty的数据同步到read中。
type Map struct {
mu Mutex // 操作dirty时候上的锁
read atomic.Value // readOnly
dirty map[interface{}]*entry
misses int // 从dirty读加1,超过一定次数dirty同步到read
}
// readOnly is an immutable struct stored atomically in the Map.read field.
type readOnly struct {
m map[interface{}]*entry
amended bool // 如果dirty中有的read中没有的,标记为true
}
// expunged is an arbitrary pointer that marks entries which have been deleted
// from the dirty map.
var expunged = unsafe.Pointer(new(interface{}))
type entry struct {
// If p == nil, the entry has been deleted and m.dirty == nil.
// If p == expunged, the entry has been deleted, m.dirty != nil, and the entry
// is missing from m.dirty.
p unsafe.Pointer // *interface{}
}
优点
sync.Map 的主要思想就是读写分离,空间换时间。
看看 sync.map 优点:
- 空间换时间:通过冗余的两个数据结构(read、dirty),实现加锁对性能的影响。
- 使用只读数据(read),避免读写冲突。
- 动态调整,miss次数多了之后,将dirty数据迁移到read中。
- double-checking。
- 延迟删除。 删除一个键值只是打标记,只有在迁移dirty数据的时候才清理删除的数据。
- 优先从read读取、更新、删除,因为对read的读取不需要锁。