Golang / Golang Internals and Memory Management Interview Questions
When should you use sync.Map instead of a mutex-protected regular map?
sync.Map (Go 1.9+) is a specialised concurrent map optimised for specific access patterns. It is not a general-purpose replacement for map + sync.Mutex.
| Aspect | map + sync.Mutex | sync.Map |
|---|---|---|
| API | Standard map syntax | Load, Store, LoadOrStore, Delete, Range |
| Ideal workload | General purpose, write-heavy | Read-heavy, mostly stable key sets |
| Performance on reads | Good (RWMutex) | Excellent — reads often lock-free |
| Performance on writes | Good | Slower — write path is complex |
| Key types | Any comparable | interface{} (loses type safety) |
| Zero value | Must initialise map first | Ready to use as zero value |
// sync.Map â optimised for: once written, many reads var sm sync.Map // Store sm.Store("key", 42) // Load val, ok := sm.Load("key") if ok { fmt.Println(val.(int)) // type assertion required } // LoadOrStore â atomic get-or-set actual, loaded := sm.LoadOrStore("key", 99) fmt.Println(actual, loaded) // 42 true (existing value returned) // Range â iterate (snapshot semantics during iteration not guaranteed) sm.Range(func(k, v any) bool { fmt.Println(k, v) return true // return false to stop iteration }) // mutex-protected map â preferred for write-heavy or type-safe needs type SafeMap[K comparable, V any] struct { mu sync.RWMutex m map[K]V } func (s *SafeMap[K, V]) Get(k K) (V, bool) { s.mu.RLock() defer s.mu.RUnlock() v, ok := s.m[k] return v, ok }
sync.Map uses two internal maps: a read-only map (accessed without locks using atomic loads) and a dirty map (accessed under a mutex) for new and updated keys. A key migrates from dirty to read when enough dirty reads occur. This optimises read performance but makes writes heavier. Use it when: caches with stable keys (add once, read many), or when goroutines read disjoint key sets.
More Related questions...