背景
go语言1.9之前map都是并发不安全的. 如果多个协程并发读写map.那么将会产生不可预知事件.造成很难排查的bug. 对系统很不好.

版本一,先看go 1.9之前并发读写不加锁
package main
func main() {
m := make(map[int]int)
go func1() { //协程1
for {
read := m[1] 并发读
...
}
}()
go func2() { //协程2
for {
m[2] = 2 // 并发写
}
}()
}
上面代码将会出现bug,甚至panic
加锁 解决并发安全问题
package main
func main() {
m := make(map[int]int)
mc := sync.Mutex
go func1() { //协程1
for {
mc.Lock()
read := m[1] 并发读
mc.Unlock()
...
}
}()
go func2() { //协程2
for {
mc.Lock()
m[2] = 2 // 并发写
m.UnLock()
}
}()
}
经过上面每一步读写共享map前后加锁,解锁. 达到协程安全.
Go 1.9 以后官方给出了sync.Map 同步map. 其实内部也是基于锁,但是天生协程安全.并且性能还不错
sync.map就是1.9版本带的线程安全map,主要有:
主要
Store
LoadOrStore
Load
Delete
Range
在读取之前Load. 写入之前Store
package main
func main() {
var m sync.Map
go func1() { //协程1
for {
// 无锁go 1.9 同步map 并发读
vv, ok = m.Load("1")
fmt.Println(vv, ok) //one true
...
}
}()
go func2() { //协程2
for {
// 并发写
m.Store("1", "2")
}
}()
}
同步map 注意还有dirty. range.
所以在store之前最好先读. 效率比之前的要好很多. 代码也简洁了. 建议大家使用. 另外如果需要删除所有map 只能 map = nil, make 新建map 这个时候记得一定要加锁!