今天早上一来领导告诉我消息源出问题了,赶紧检查日志,没有报错,于是跟着看nohup输出,看到一个error导致了程序崩溃,fatal error: concurrent map iteration and map write.
看到这个错误信息,很容易就想到了,可能是在多线程中,同时对map进行了遍历和写操作,导致的崩溃。然后通过对代码进行检查,发现了确实有一处地方,没有对遍历map的操作加锁,导致了这个问题。之前只考虑到了读和写会引发崩溃,直到今天发生崩溃了才发现这个问题。
上一下之前的模拟代码:
func MapMuxTest() {
mMap := make(map[int]string)
var mux sync.RWMutex
mMap[1] = "new rap"
mMap[2] = "new star"
mMap[3] = "mo"
mMap[4] = "dong"
mMap[5] = "shan"
mMap[6] = "ba"
go func(mux *sync.RWMutex, mMap map[int]string) {
ti := time.NewTimer(time.Nanosecond * 2)
idx := 1
for {
<- ti.C
mux.Lock()
mMap[idx] = "mdsb" // map write
idx++
if idx >= 7 {
idx = 1
}
mux.Unlock()
ti.Reset(time.Nanosecond * 2)
}
}(&mux, mMap)
ti := time.NewTimer(time.Millisecond)
for {
<- ti.C
// 这里没有对遍历操作加锁,导致和上面的写操作冲突
for k, _ := range mMap { // map iteration
mux.RLock()
str := mMap[k]
fmt.Println(str)
mux.RUnlock()
}
ti.Reset(time.Millisecond)
}
}
之后,把代码修改了一下,就是把加锁解锁的操作放在了遍历的外面,避免了遍历map和写map的冲突。
mux.RLock()
for k, _ := range mMap {
str := mMap[k]
fmt.Println(str)
}
mux.RUnlock()
本篇到此结束,简单记录一下这个问题。