Der gleichzeitige Zugriff auf gemeinsam genutzte Daten in Go kann eine Quelle potenzieller Fehler sein, wie z. B. Datenrennen. Wenn der Zugriff auf eine Datenstruktur gleichzeitig erfolgt, d. h. mehrere Goroutinen gleichzeitig darauf zugreifen können, ist es wichtig sicherzustellen, dass die Daten synchron gelesen und geschrieben werden, um Inkonsistenzen zu vermeiden.
Berücksichtigen Sie die folgenden Go-Struktur-Metadaten:
type Metadata struct { mu sync.RWMutex // ? key bool }
Wie wir sehen können, die Metadaten struct enthält einen Feldschlüssel vom Typ bool und ein weiteres Feld mu vom Typ sync.RWMutex, das eine Implementierung einer Lese-/Schreibsperre ist.
Wenn wir eine erstellen Instanz von Metadaten und ermöglichen mehreren Goroutinen das gleichzeitige Lesen und Schreiben ihrer Felder, kann es zu Datenwettläufen kommen. Ein Datenwettlauf tritt auf, wenn mehrere Goroutinen gleichzeitig auf dieselben Daten zugreifen und mindestens eine von ihnen einen Schreibvorgang ausführt.
Der folgende Code demonstriert den gleichzeitigen Lese- und Schreibzugriff auf die Metadatenstruktur ohne explizite Sperre:
func concurrentStruct() { m := new(Metadata) for i := 0; i < 100000; i++ { go func(metadata *Metadata) { for { readValue := metadata.key if readValue { metadata.key = false } } }(m) go func(metadata *Metadata) { for { metadata.key = true } }(m) } select {} }
In diesem Code erstellen wir eine Goroutine, die das Schlüsselfeld gleichzeitig liest und schreibt. Wir verwenden eine Select-Anweisung, um die Haupt-Goroutine zu blockieren und die Ausführung der gleichzeitigen Goroutinen zu ermöglichen. Wenn wir das Programm mit dem Befehl „go run -race“ ausführen, erhalten wir eine Warnung, die auf ein DATA RACE hinweist.
Das Programm läuft jedoch ohne Absturz weiter. Dies liegt daran, dass die Go-Laufzeit über eine integrierte Parallelitätsprüfung verfügt, diese jedoch keine sichere Ausführung garantiert. In diesem Fall kann der Datenwettlauf zu undefiniertem Verhalten und falschen Ergebnissen führen.
Um Datenwettläufe beim gleichzeitigen Lesen und Schreiben in Strukturen zu verhindern, müssen wir die richtige Methode verwenden Verriegelungsmechanismen. Eine Möglichkeit besteht darin, Mutexe zu verwenden, wie im folgenden Code gezeigt:
func concurrentStructWithMuLock() { m := new(Metadata) go func(metadata *Metadata) { for { metadata.mu.Lock() readValue := metadata.key if readValue { metadata.key = false } metadata.mu.Unlock() } }(m) go func(metadata *Metadata) { for { metadata.mu.Lock() metadata.key = true metadata.mu.Unlock() } }(m) select {} }
In diesem Code haben wir der Metadata-Struktur eine Lese-/Schreibsperre hinzugefügt und verwenden mu.Lock() und mu. Unlock() zum Synchronisieren des Zugriffs auf das Schlüsselfeld. Wenn Sie das Programm mit go run -race ausführen, werden keine Warnungen mehr generiert, was darauf hinweist, dass keine Datenrennen stattfinden.
Das obige ist der detaillierte Inhalt vonWie kann ich Data Races beim gleichzeitigen Lesen und Schreiben von Go-Strukturen verhindern?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!