【GoLand】sync.Map的使用与原理

291 阅读1分钟

一、sync.Map的使用

1.Map的增加、删除、获取、遍历

package main

import (
    "fmt"
    "sync"
)

type Person struct {
    name string
    age int32
}

var personList sync.Map

func main () {
    // 向Map中添加元素
    personList.Store(11111, &Person{"Sam", 21})
    personList.Store(11112, &Person{"Sam1", 22})
    personList.Store(11113, &Person{"Sam2", 23})
    personList.Store(11114, &Person{"Sam3", 24})
    // 遍历获取Map中的元素,需要使用回调函数,可以理解为对每一个Map元素做某种操作
    personList.Range(func(key, value interface{}) bool {
        // 因为value是一个空接口类型,需要强转为对应结构体指针
        node := value.(*Person)
        fmt.Println(key, node.name, node.age)
        return true
    })
    // 从Map中删除元素
    personList.Delete(11111)
    personList.Delete(11112)
    // 从Map中获取元素
    if value, ok := personList.Load(11111); ok {
        fmt.Println(value)
    } else {
        fmt.Println("Sam has been deleted")
    }

    if value, ok := personList.Load(11113); ok {
        fmt.Println(value)
    } else {
        fmt.Println("Sam3 has been deleted")
    }
}

二、sync.Map的原理

  • 通过 read 和 dirty 两个字段将读写分离
  • 读的数据存在只读字段 read 上,将最新写入的数据则存在 dirty 字段上
  • 读取时会先查询 read,不存在再查询 dirty,写入时则只写入 dirty
  • 读取 read 并不需要加锁,而读或写 dirty 都需要加锁
  • 另外有 misses 字段来统计 read 被穿透的次数(被穿透指需要读 dirty 的情况),超过一定次数则将 dirty 数据同步到 read 上
  • 对于删除数据则直接通过标记来延迟删除

三、参考资料

juejin.cn/post/684490…