一.问题
map是线程不安全的,即使并发读写没有冲突也会报错(fatal error: concurrent map read and map write):
func main() {
m := make(map[int]int)
go func() {
for {
_ = m[1]
}
}()
go func() {
for {
m[2] = 2
}
}()
time.Sleep(time.Second * 1)
}
报错原因:
写的时候设置了h.flags,获取的时候检查报错
写完会清除标志位
二.解决办法
1)使用读写锁sync.RWMutex:
var counter = struct{
sync.RWMutex
m map[string]int
}{m: make(map[string]int)}
counter.RLock() n := counter.m["some_key"] counter.RUnlock() fmt.Println("some_key:", n)
counter.Lock() counter.m["some_key"]++ counter.Unlock()
2)使用类似java的Concurrenthashmap(https://github.com/orcaman/concurrent-map)
3)使用sync.Map
func main() {
m := sync.Map{}
m.Store(1, 1)
m.Store("1", "1")
fmt.Println(m.Load("1"))
m.Delete("1")
fmt.Println(m.Load("1"))
}
补充:对于不容易发现的并发问题,可以使用-race参数进行并发检测
func main() {
a := 1
go func() {
a = 2
}()
a = 3
fmt.Println(a)
time.Sleep(time.Second * 1)
}