map不是并发安全的 , 当有多个并发的groutine读写同一个map时
会出现panic错误
concurrent map writes
例如下面的代码会出现这个错误:
- var mMap map[int]int
- func TestMyMap(t *testing.T) {
- mMap = make(map[int]int)
- for i := 0; i < 5000; i++ {
- go func() {
- mMap[i] = i
- }()
- go readMap(i)
- }
- }
- func readMap(i int) int {
- return mMap[i]
- }
解决这个错误可以有多种方式 , 现在采取读写锁的方式 ,
并发访问map是不安全的,会出现未定义行为,导致程序退出。所以如果希望在多协程中并发访问map,必须提供某种同步机制,一般情况下通过读写锁sync.RWMutex实现对map的并发访问控制,将map和sync.RWMutex封装一下,可以实现对map的安全并发访问
改造后的代码
- type SMap struct {
- sync.RWMutex
- Map map[int]int
- }
- func (l *SMap) readMap(key int) (int, bool) {
- l.RLock()
- value, ok := l.Map[key]
- l.RUnlock()
- return value, ok
- }
- func (l *SMap) writeMap(key int, value int) {
- l.Lock()
- l.Map[key] = value
- l.Unlock()
- }
- var mMap *SMap
- func TestMyMap(t *testing.T) {
- mMap = &SMap{
- Map: make(map[int]int),
- }
- for i := 0; i < 5000; i++ {
- go func() {
- mMap.writeMap(i, i)
- }()
- go readMap(i)
- }
- }
- func readMap(i int) (int, bool) {
- return mMap.readMap(i)
- }
有这三种方式:
1.使用channel
2.使用sync.map
3.使用map但必须进行加锁