1. 前提
Go语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全的。
2. map并发读写测试
package main
import (
"os/signal"
"runtime"
"syscall"
)
func main() {
// 创建一个int到int的映射
m := make(map[int]int)
// 开启一段并发代码
go func() {
// 不停地对map进行写入
for {
m[1] = 1
}
}()
// 开启一段并发代码
go func() {
// 不停地对map进行读取
for {
_ = m[1]
}
}()
signal.Ignore(syscall.SIGHUP)
runtime.Goexit()
}
运行时报错fatal error: concurrent map read and map write
3. 接下来用并发安全的sync.Map来测试
package main
import (
"fmt"
"os/signal"
"runtime"
"sync"
"syscall"
)
func main() {
// 创建一个int到int的映射
m := sync.Map{}
// 开启一段并发代码
go func() {
// 不停地对map进行写入
for {
m.Store(1,1)
}
}()
// 开启一段并发代码
go func() {
// 不停地对map进行读取
for {
if v, ok := m.Load(1); ok{
fmt.Println(v)
}
}
}()
signal.Ignore(syscall.SIGHUP)
runtime.Goexit()
}
运行时会一直输出1而不会报错
4. sync.Map基本操作
4.1 创建
直接声明,不需要makevar m sync.Map
4.2 插入、修改
- 如果key不存在,插入value;
- 如果key存在则修改其值
m.Store(key,value)
4.3 插入或查找
- 如果key不存在,插入value,返回插入value的值,ok为false
- 如果key存在,返回原map中value的值,ok为true
value,ok := m.LoadOrStore(key,value)
4.4 删除
m.Delete(key)
4.5 查找
v,ok := m.Load(key)
4.6 遍历
m.Range(func(k, v interface{}) bool {
fmt.Println("interate:",k,v)
return true
})