当多线程对这两种数据类型同时进行 写
操作时,如果不对其做线程安全处理,得到的结果往往不是所期望的,还有可能降低性能或抛出错误。
常用的简单方法是加锁:
1
2
3
4
5
6
7
8
9
10
var lock = sync.Mutex{}
var myList = []int{}
lock.Lock() // 加锁
myList = append(myList, 1)
lock.Unlock() // 解锁
map 类型除了可以使用上面的方式,还可以使用系统自带的 sync.Map
类型来代替,只是对 map 的操作稍有点不同。
1
2
3
4
5
6
7
8
var mp = &sync.Map{}
mp.Store("k", 1)
if v, ok := mp.Load("k"); ok {
fmt.Println(v)
}
mp.Delete("k")
sync.Map 还有几个有用的方法:
1
2
LoadAndDelete(k)
LoadOrStore(k, v)
可以使用 Range
来遍历删除所有键
1
2
3
4
mp.Range(func(k, _ interface{}) bool {
mp.Delete(k)
return true
})
其实 map 清空所有键值,使用下面的方法更佳:
1
mp = &sync.Map{}
There are 5 Comments to "Golang 中两个基本数据 map、slice 并发安全使用方法"
在使用 sync.Map 做网站全局缓存时发现一个问题:
当 Delete 一个键后,再读取其它的 key 时可能出现一些意外错误,而当删除全部的 key 则不会出现这样的情况。
@简单猪 #1 估计是我的姿势不对😄
@简单猪 #1 是初始化时的一个小细节引起的问题
在实际使用中发现,
mp
会不可预期的出现问题,mp2
正常。@简单猪 #3 错觉!!问题依旧,最终还是弃用
sync.Map
@简单猪 #4 使用
fastcache