type Map struct {
// 保护加锁字段
mu Mutex
// readOnly 结构是只读,但其中的操作也有写
read atomic.Value
// 最终写入的数据
dirty map[interface{}]*entry
// 计数器,每次read没有,读dirty就+1
misses int
}
type readOnly struct {
// 只读map
m map[interface{}]*entry
// 脏映射中有不在m中的值就true-> dirty被提升了置为false,dirty=nil,true表示上一次已经把read拷贝到dirty,且设置新的值
amended bool // true if the dirty map contains some key not in m.
}
// expunge 代表 dirty 中被删掉的情况
var expunged = unsafe.Pointer(new(interface{}))
// 存储值的指针
type entry struct {
p unsafe.Pointer // *interface{}
}
// read里面有key就直接原子读,否则如果dirty!=nil就尝试从dirty读(如果错过次数太多就将dirty提升,设置dirty=nil,amended=false)
func (m *Map) Load(key interface{}) (value interface{}, ok bool) {
// 尝试从read读readonly对象
read, _ := m.read.Load().(readOnly)
e, ok := read.m[key]
if !ok && read.amended {
m.mu.Lock()
read, _ = m.read.Load().(readOnly)
e, ok = read.m[key]
if !ok && read.amended {
e, ok = m.dirty[key]
// 标记错过,如果错过次数太多就将dirty提升
m.missLocked()
}
m.mu.Unlock()
}
if !ok {
return nil, false
}
// 返回结果
return e.load()
}
// read里面或者dirty有key就乐观锁或原子更新对应的e.p,否则如果dirty为nil就拷贝read到dirty(amended=false,e.p如果等于nil->expunged),添加k,v到dirty
func (m *Map) Store(key, value interface{}) {
read, _ := m.read.Load().(readOnly)
// 如果read里面有就更新read
if e, ok := read.m[key]; ok && e.tryStore(&value) {
return
}
m.mu.Lock()
read, _ = m.read.Load().(readOnly)
// read有且标记为删除 则置为nil,然后添加到dirty中,最后更新read值
if e, ok := read.m[key]; ok {
// dirty != nil
if e.unexpungeLocked() {
// 添加dirty
m.dirty[key] = e
}
e.storeLocked(&value)
} else if e, ok := m.dirty[key]; ok { // read没有,dirty中有key就更新v
e.storeLocked(&value)
} else {
// 这个表示dirty可能为nil
if !read.amended {
// 将read复制到dirty,同时把nil更改为标记删除
m.dirtyLocked()
// 标记dirty不为nil且数据多
m.read.Store(readOnly{m: read.m, amended: true})
}
// dirty中添加value
m.dirty[key] = newEntry(value)
}
m.mu.Unlock()
}
// read中有key则将e.p->nil,否则如果dirty!=nil,去dirty中找并删除key,最后如果这个值存在e.p->nil
func (m *Map) Delete(key interface{}) {
m.LoadAndDelete(key)
}
// read中有key则将e.p->nil,否则如果dirty中有值,去dirty中找并删除key,最后如果这个值存在e.p->nil
func (m *Map) LoadAndDelete(key interface{}) (value interface{}, loaded bool) {
read, _ := m.read.Load().(readOnly)
e, ok := read.m[key]
// read中没有且dirty数据多就去dirty中找,然后删除k并增加穿透次数,最后如果有就更新值为nil
if !ok && read.amended {
m.mu.Lock()
read, _ = m.read.Load().(readOnly)
e, ok = read.m[key]
if !ok && read.amended {
e, ok = m.dirty[key]
delete(m.dirty, key)
m.missLocked()
}
m.mu.Unlock()
}
// read中有就尝试把e.p置为nil
if ok {
return e.delete()
}
return nil, false
}```
[go]浅谈sync.Map
最新推荐文章于 2025-04-10 11:05:04 发布