Tag Archives: concurrent map writes map

[Go] Solve the fatal error: concurrent map writes map is not concurrently safe

Map is not concurrently safe, when there are multiple concurrent groutines reading and writing the same map 

Panic error will occur

concurrent map writes

 

For example, the following code will cause this error:

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]
}

There are many ways to solve this error. Now we take the way of read-write lock.

Concurrent access to the map is not safe, and undefined behavior will occur, causing the program to exit. Therefore, if you want to access the map concurrently in a multi-coroutine, you must provide a synchronization mechanism. Generally, the concurrent access control to the map is achieved through the read-write lock sync.RWMutex, and the map and sync.RWMutex can be encapsulated to achieve the map Secure concurrent access

Transformed code

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)
}

 There are three ways:

1. Use channel
2. Use sync.map
3. Use map but must be locked