How does Go ensure the safety of working with maps during concurrent access, and what synchronization mechanisms are used in practice?
sobes.tech AI
Answer from AI
In the Go language, the built-in map type is not thread-safe for concurrent reading and writing from multiple goroutines. If multiple goroutines modify or read a map simultaneously without synchronization, it leads to a concurrent map read and map write panic.
Go does not provide automatic protection for maps against concurrent access, so the responsibility for synchronization lies with the developer.
To safely work with maps in concurrent access scenarios, the following mechanisms are used:
-
sync.Mutex or sync.RWMutex — lock access to the map during reading and writing.
RWMutexallows multiple goroutines to read the map simultaneously but blocks writing. -
sync.Map — a specialized thread-safe type from the standard library, optimized for scenarios with many reads and infrequent writes. It implements internal synchronization and is suitable for caching and other cases.
Example with sync.RWMutex:
var (
m = make(map[string]int)
mu sync.RWMutex
)
func read(key string) (int, bool) {
mu.RLock()
defer mu.RUnlock()
val, ok := m[key]
return val, ok
}
func write(key string, val int) {
mu.Lock()
defer mu.Unlock()
m[key] = val
}
Example with sync.Map:
var m sync.Map
func write(key string, val int) {
m.Store(key, val)
}
func read(key string) (int, bool) {
val, ok := m.Load(key)
if !ok {
return 0, false
}
return val.(int), true
}
Thus, Go provides basic tools for synchronizing access to maps, but the developer must explicitly use them to prevent races and crashes.