day06-go sync.map

作者: Winnifred_ | 来源:发表于2020-05-13 14:34 被阅读0次

    https://mp.weixin.qq.com/s/mXOU8TElP8bbqaybRKN8eA

    go原生的map是不支持线程安全的,在对她并发操作的时候必须要加锁,

    sync.map支持store,delete,LoadOrStore,range等操作,具体方法请自行测试

    sync.map利用read 和 dirty 两个 map 来进行读写分离,降低锁时间来提高效率

    数据结构为

    type Map struct {

     mu Mutex

     read atomic.Value // readOnly

     dirty map[interface{}]*entry

     misses int

    }

    // readOnly is an immutable struct stored atomically in the Map.read field.

    type readOnly struct {

     m       map[interface{}]*entry

     amended bool // true if the dirty map contains some key not in m.

    }

    read,dirty则是真正存储k,v的结构,可以看到read是atomic.Value 可以被并发的读,而dirty是一个原始的map,它包含新写入的key以及read中所有未被删除的key,在对dirty进行load/store时需要进行加锁操作,因此他可以很快的被提升为read,而向外提供服务

    read和dirty都有一个entry结构

    type entry struct {

     p unsafe.Pointer // *interface{}

    }

    可以看到read和dirty都各自维护了一个key,但是value值都指向了同一个地址

    总结:

    sync.map 是线程安全的,读取,插入,删除也都保持着常数级的时间复杂度。

    通过读写分离,降低锁时间来提高效率,适用于读多写少的场景。

    Range 操作需要提供一个函数,参数是 k,v,返回值是一个布尔值:f func(key, value interface{}) bool。

    调用 Load 或 LoadOrStore 函数时,如果在 read 中没有找到 key,则会将 misses 值原子地增加 1,当 misses 增加到和 dirty 的长度相等时,会将 dirty 提升为 read。以期减少“读 miss”。

    新写入的 key 会保存到 dirty 中,如果这时 dirty 为 nil,就会先新创建一个 dirty,并将 read 中未被删除的元素拷贝到 dirty。

    当 dirty 为 nil 的时候,read 就代表 map 所有的数据;当 dirty 不为 nil 的时候,dirty 才代表 map 所有的数据

    sync.Map适合读多写少的情况

    相关文章

      网友评论

        本文标题:day06-go sync.map

        本文链接:https://www.haomeiwen.com/subject/unfnnhtx.html