ProgrammierungBackend-Entwickler

Beschreiben Sie den Mechanismus zum Schutz vor Data Races bei der Arbeit mit Maps in Go. Welche Garantien gibt es und warum führt die einfache Arbeit mit Maps in mehreren Goroutinen ohne Schutz zu Fehlern?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

In Go sind Maps standardmäßig nicht threadsicher. Wenn mehrere Goroutinen gleichzeitig in dieselbe Map schreiben oder lesen, ohne synchronisiert zu sein, tritt ein Data Race auf, das zu einem Panic-Zustand fatal error: concurrent map read and map write oder zu beschädigten Daten führen kann.

Für einen threadsicheren Umgang mit Maps ist es notwendig:

  • Die primitives sync.Mutex oder sync.RWMutex zu verwenden, um alle Lese- und Schreiboperationen zu schützen.
  • Oder das Paket sync.Map zu verwenden, das für hochbelastete konkurrierende Szenarien gedacht ist.
var mu sync.RWMutex m := make(map[string]int) // Schreiben mu.Lock() m["key"] = 1 mu.Unlock() // Lesen mu.RLock() v := m["key"] mu.RUnlock() // Oder sync.Map var sm sync.Map sm.Store("key", 1) v, _ := sm.Load("key")

Fangfrage

Warum ist das gleichzeitige Lesen und Schreiben aus verschiedenen Goroutinen in einer Map in Go so gefährlich, auch wenn Map ein eingebauter Typ ist?

Antwort: In Go bietet der eingebaute Typ Map keine Synchronisation. Der gleichzeitige Zugriff auf eine Map aus mehreren Goroutinen führt nicht nur zu inkorrekten Werten, sondern kann auch zu einem Absturz des Programms führen. Selbst gleichzeitiges Lesen und Schreiben (wenn keine überlappenden Schlüssel vorhanden sind!) kann einen fatalen Fehler verursachen. Dies unterscheidet sich von einigen anderen Programmiersprachen, in denen Sammlungen „tolerant“ für konkurrierende Zugriffe sind.

Beispiele für reale Fehler aufgrund mangelnden Wissens über die Thematik


Geschichte

In einem realen Projekt verwendete ein Entwickler eine globale Map, um Daten zwischenzuspeichern. Der Dienst funktionierte stabil in Tests, fiel jedoch bei Lasttests und in der Produktion mit der Fehlermeldung fatal error: concurrent map read and map write. Der Grund war der parallele Zugriff auf die Map aus verschiedenen HTTP-Anfragen ohne Verwendung eines Mutex.


Geschichte

In einer Go-Webanwendung beschloss ein Programmierer, die Leistung zu verbessern und verwendete eine normale Map als Verbindungs-Pool, in der Annahme, dass die Multithreading-Fähigen vom Framework bereitgestellt wurden. Bei plötzlichem Traffic-Anstieg begann der Dienst ohne ersichtlichen Grund abzustürzen: Aufgrund des Data Races wurden die Daten in der Map beschädigt, was zu Paniken führte.


Geschichte

In einem internen Go-Dienst verwendete die Anwendung eine Map zur Sammlung von Statistiken „in Echtzeit“, in der Annahme, dass hauptsächlich Schreibzugriffe stattfanden. Tatsächlich fragten jedoch andere Teile des Codes regelmäßig Daten für die Erstellung von Berichten ab, was zu schwer nachvollziehbaren Abstürzen nur einmal täglich führte – genau dann, wenn die Statistiken ausgelöst wurden. Die Analyse ergab, dass Lese- und Schreibzugriffe ohne jede Sperre überlappten.