Concurrent access of maps
suggest changeMaps in Go are not safe for concurrency.
One option to ensure safe concurrent access is to use sync.Mutex
or sync.RWMutex
and lock around all map reads and writes.
As an example, a simple wrapper around a map
that is safe for concurrent use as long as it's done by Get
, Set
and Add
methods:
package main
import (
"fmt"
"sync"
)
// ConcurrentMap is a wrapper around map that is safe for concurrent use
type ConcurrentMap struct {
sync.RWMutex
m map[string]int
}
// Get gets a value for a key
func (r *ConcurrentMap) Get(key string) int {
r.RLock()
defer r.RUnlock()
return r.m[key]
}
// Set sets a key to a given value
func (r *ConcurrentMap) Set(key string, val int) {
r.Lock()
defer r.Unlock()
r.m[key] = val
}
// Add increases the value under a key by n
func (r *ConcurrentMap) Add(key string, n int) int {
r.Lock()
defer r.Unlock()
r.m[key] += n
return r.m[key]
}
func main() {
counter := ConcurrentMap{m: make(map[string]int)}
n := counter.Add("some_key", 2)
fmt.Printf("Final value is: %d\n", n)
}
Final value is: 2
sync.RWMutex
can be faster because it allows multiple readers. On the downside you have to be more careful to ensure you're not writing under RLock
. The performance difference with sync.Mutex
will be negligible unless there's a high-contention on the lock or the locks are held for a long time.
Found a mistake? Have a question or improvement idea?
Let me know.
Table Of Contents