I\'m writing minecraft server in Go, when server is being stressed by 2000+ connections I get this crash:
fatal error: concurrent map read and map write/root/w
Generally speaking (without having access to the code where the error occurs) you have a few options. Here are two of them:
Control access to the map with sync.RWMutex{}
. Use this option if you have single reads and writes, not loops over the map. See RWMutex
Here a sample with access control to someMap
via someMapMutex
:
var (
someMap = map[string]string{}
someMapMutex = sync.RWMutex{}
)
go func() {
someMapMutex.Lock()
someMap["key"] = "value"
someMapMutex.Unlock()
}()
someMapMutex.RLock()
v, ok := someMap["key"]
someMapMutex.RUnlock()
if !ok {
fmt.Println("key missing")
return
}
fmt.Println(v)
Use a syncmap.Map{}
instead of a normal map
. This map is already taking care of race issues but may be slower depending on your usage. syncmap.Map{}
s main advantage lies with for loops. See syncmap
var (
someMap = syncmap.Map{}
)
go func() {
someMap.Store("key", "value")
}()
v, ok := someMap.Load("key")
if !ok {
fmt.Println("key missing")
return
}
fmt.Println(v)
// with syncmap, looping over all keys is simple without locking the whole map for the entire loop
someMap.Range(func(key, value interface{}) bool {
// cast value to correct format
val, ok := value.(string)
if !ok {
// this will break iteration
return false
}
// do something with key/value
fmt.Println(key, val)
// this will continue iterating
return true
})
You should test your server with -race
option and then eliminate all the race conditions it throws. That way you can easier eliminate such errors before they occur.
go run -race server.go
See golang race detector