go / intermediate
Snippet
Thread-sicherer Map-Zugriff mit Lese-Schreib-Mutexen
In Go sind Maps nicht für die gleichzeitige Verwendung (Concurrency) sicher. Wenn zwei Goroutinen gleichzeitig in eine Map schreiben oder eine liest, während eine andere schreibt, stürzt das Programm mit einem fatalen Fehler ab. Um dies zu verhindern, kapseln wir die Map in einem Struct zusammen mit einem sync.RWMutex. Die Methode Lock lockt alle anderen Lese- und Schreibzugriffe, während RLock mehrere gleichzeitige Leser zulässt, aber Schreiber blockiert.
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"))}
Erklärung
1
type SafeCounter struct
Definiert einen benutzerdefinierten Typ, der ein sync.RWMutex und eine Map einpackt und so die Daten und ihren Synchronisationsmechanismus miteinander verbindet.
2
c.mu.Lock()
Erwirbt eine exklusive Schreibsperre. Keine andere Goroutine kann lesen oder schreiben, bis Unlock aufgerufen wird.
3
defer c.mu.Unlock()
Stellt sicher, dass die Schreibsperre freigegeben wird, wenn die Methode Inc zurückkehrt, um Deadlocks zu verhindern.
4
c.mu.RLock()
Erwirbt eine Lesesperre. Mehrere Leser können diese Sperre gleichzeitig halten, aber Schreiber werden blockiert.