Go语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全的。
如果想实现并发线程安全有两种方法:
https://github.com/golang/go/blob/master/src/sync/map.go
具体数据结构可参考:
https://blog.csdn.net/u010853261/article/details/103848666
https://www.haohongfan.com/docs/gohandbook/sync-chapter/2021-05-10-sync-map/
map+Mutex: 通过Mutex互斥锁来实现多个goroutine对map的串行化访问,读写都需要通过Mutex加锁和释放锁,适用于读写比接近的场景
map+RWMutex:通过RWMutex来实现对map的读写进行读写锁分离加锁,从而实现读的并发性能提高,同Mutex相比适用于读多写少的场景
sync.Map:底层通分离读写map和原子指令来实现读的近似无锁,并通过延迟更新的方式来保证读的无锁化。读多修改少,元素增加删除频率不高的情况,在大多数情况下替代上述两种实现
package main
import (
"fmt"
"sync"
)
func main() {
var m sync.Map
//添加一个元素
m.Store(1, "a")
m.Store("a", 2)
//读取一个元素
fmt.Println(m.Load(1)) //a true
fmt.Println(m.Load("a")) //2 true
//读取不存在的元素
fmt.Println(m.Load(2)) // false
//存在就返回,不存在就插入
fmt.Println(m.LoadOrStore("3", 33)) //33 false
fmt.Println(m.Load("3")) //33 true
//如果存在的话,同时删除这个 key
fmt.Println(m.LoadAndDelete("3")) // 33 true
//删除某个元素
m.Delete("3")
// 遍历所有sync.Map中的键值对
m.Range(func(k, v interface{}) bool {
fmt.Println("iterate:", k, v)
return true
})
}
通过以上示例可以看到sync.map具有以下特性:
https://juejin.cn/post/6844904100287496206
https://pkg.go.dev/sync#Map
https://blog.csdn.net/u010853261/article/details/103848666
https://medium.com/@deckarep/the-new-kid-in-town-gos-sync-map-de24a6bf7c2c
https://www.haohongfan.com/docs/gohandbook/sync-chapter/2021-05-10-sync-map/