sync.Map 是1.9版本才加入的,是线程并发安全的map,类型可以看做map[interface{}]interface{}。
结构
Map
type Map struct { mu Mutex read atomic.Value dirty map[interface{}]*entry misses int }
|
readOnly
type readOnly struct { m map[interface{}]*entry amended bool }
|
entry
type entry struct { p unsafe.Pointer }
|
Load 查找
根据key来查找 value, 函数为 Load(),源码如下:
func (m *Map) Load(key interface{}) (value interface{}, ok bool) { 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] m.missLocked() } m.mu.Unlock() } if !ok { return nil, false } return e.load() }
|
从函数可以看出,如果查询的键值正好在m.read中,不需要加锁,直接返回结果,优化了性能。
即使不在read中,经过几次miss后, m.dirty中的数据也会迁移到m.read中,这时又可以从read中查找。所以对于更新/增加较少,加载存在的key很多的case,性能基本和无锁的map类似。
missLockerd 迁移数据
func (m *Map) missLocked() { m.misses++ if m.misses < len(m.dirty) { return } m.read.Store(readOnly{m: m.dirty}) m.dirty = nil m.misses = 0 }
|
Store 存储
func (m *Map) Store(key, value interface{}) { read, _ := m.read.Load().(readOnly) if e, ok := read.m[key]; ok && e.tryStore(&value) { return } m.mu.Lock() read, _ = m.read.Load().(readOnly) if e, ok := read.m[key]; ok { if e.unexpungeLocked() { m.dirty[key] = e } e.storeLocked(&value) } else if e, ok := m.dirty[key]; ok { e.storeLocked(&value) } else { if !read.amended { m.dirtyLocked() m.read.Store(readOnly{m: read.m, amended: true}) } m.dirty[key] = newEntry(value) } m.mu.Unlock() }
|
操作都是先从m.read开始,不满足条件再加锁,然后操作m.dirty。
Delete 删除
func (m *Map) Delete(key interface{}) { 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 { delete(m.dirty, key) } m.mu.Unlock() } if ok { e.delete() } }
|
使用
package main
import ( "fmt" "sync" )
func main() { var sm sync.Map
sm.Store("www", "2343125") sm.Store("test", 111)
var v interface{}
v, _ = sm.Load("www") fmt.Printf("%T", v) sm.Delete("test") v, _ = sm.Load("test") fmt.Printf("%T", v) }
|
参考