How to protect against errors when writing to a map concurrently?
sobes.tech AI
Answer from AI
To protect against errors during concurrent writes to a map in Golang, which are not thread-safe by default, the following mechanisms are used:
-
sync.Mutex: Lock the map before writing and unlock after.import "sync" type SafeMap struct { mu sync.Mutex data map[string]int } func NewSafeMap() *SafeMap { return &SafeMap{ data: make(map[string]int), } } func (sm *SafeMap) Set(key string, value int) { sm.mu.Lock() defer sm.mu.Unlock() sm.data[key] = value } func (sm *SafeMap) Get(key string) (int, bool) { sm.mu.Lock() defer sm.mu.Unlock() val, ok := sm.data[key] return val, ok } -
sync.RWMutex: Allows multiple goroutines to read from the map simultaneously but blocks writing during concurrent read or write.import "sync" type SafeMapRWMutex struct { mu sync.RWMutex data map[string]int } func NewSafeMapRWMutex() *SafeMapRWMutex { return &SafeMapRWMutex{ data: make(map[string]int), } } func (sm *SafeMapRWMutex) Set(key string, value int) { sm.mu.Lock() // Write lock defer sm.mu.Unlock() sm.data[key] = value } func (sm *SafeMapRWMutex) Get(key string) (int, bool) { sm.mu.RLock() // Read lock defer sm.mu.RUnlock() val, ok := sm.data[key] return val, ok } -
sync.Map: A specialized thread-safe type optimized for scenarios where the set of keys is relatively stable and writes are rare, or when multiple goroutines read and write for disjoint sets of keys.import "sync" var safeMap sync.Map // Declaration func UseSyncMap() { safeMap.Store("key1", 10) // Write if val, ok := safeMap.Load("key1"); ok { // Read // Use val } safeMap.Delete("key1") // Delete }
Comparison of approaches:
| Mechanism | Advantages | Disadvantages | Use case |
|---|---|---|---|
sync.Mutex |
Simple to use | Blocks all operations during write | Simple scenarios with low concurrency or roughly equal read/write. |
sync.RWMutex |
Allows parallel reading | More complex than sync.Mutex. Write blocks reads and other writes. |
Scenarios with frequent reads and rare writes. |
sync.Map |
Optimized for specific scenarios | Has a limited API. May be slower than Mutex if access is fully random. |
Scenarios with relatively stable keys or disjoint key sets for different goroutines. |
The choice of approach depends on the nature of concurrent access to the map. For general cases, sync.Mutex or sync.RWMutex are often sufficient. For specific scenarios, sync.Map can provide better performance.