go / intermediate
Snippet
Thread-Safe Map Access Using Read-Write Mutexes
In Go, maps are not safe for concurrent use. If two goroutines write to a map at the same time, or one reads while another writes, the program will panic with a fatal concurrent map write error. To prevent this, we encapsulate the map within a struct alongside a sync.RWMutex. The Lock method blocks all other reads and writes, while RLock allows multiple concurrent readers but blocks writers.
snippet.go
go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package mainimport ("fmt""sync")type SafeCounter struct {mu sync.RWMutexv map[string]int}func (c *SafeCounter) Inc(key string) {c.mu.Lock()defer c.mu.Unlock()c.v[key]++}func (c *SafeCounter) Value(key string) int {c.mu.RLock()defer c.mu.RUnlock()return c.v[key]}func main() {c := SafeCounter{v: make(map[string]int)}var wg sync.WaitGroupfor i := 0; i < 1000; i++ {wg.Add(1)go func() {defer wg.Done()c.Inc("somekey")}()}wg.Wait()fmt.Println("Value:", c.Value("somekey"))}
Breakdown
1
type SafeCounter struct
Defines a custom type wrapping a sync.RWMutex and a map, tying the data and its synchronization mechanism together.
2
c.mu.Lock()
Acquires an exclusive write lock. No other goroutine can read or write until Unlock is called.
3
defer c.mu.Unlock()
Ensures the write lock is released when the Inc method returns, preventing deadlocks.
4
c.mu.RLock()
Acquires a read lock. Multiple readers can hold this lock simultaneously, but writers will be blocked.