Heim >Backend-Entwicklung >Golang >Wie kann ich Data Races beim gleichzeitigen Lesen und Schreiben von Go-Strukturen verhindern?

Wie kann ich Data Races beim gleichzeitigen Lesen und Schreiben von Go-Strukturen verhindern?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-12-25 04:21:09540Durchsuche

How Can I Prevent Data Races When Concurrently Reading and Writing Go Structs?

Gleichzeitiges Lesen und Schreiben von Go-Strukturen ohne explizite Sperrung

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.

Gleichzeitiger Zugriff auf Strukturen

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.

Datenrennen in Structs

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.

Auflösen von Datenwettläufen in Strukturen

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn