Heim  >  Artikel  >  Backend-Entwicklung  >  Warum ist das Anhängen an ein Slice in gleichzeitigen Goroutinen nicht threadsicher?

Warum ist das Anhängen an ein Slice in gleichzeitigen Goroutinen nicht threadsicher?

Linda Hamilton
Linda HamiltonOriginal
2024-11-10 00:49:02723Durchsuche

Why is Appending to a Slice in Concurrent Goroutines Not Thread-Safe?

Gleichzeitige Slices: Anhängen nicht threadsicher

Frage:

Bedenken Sie den folgenden Code das an ein Slice angehängt wird und mehrere Goroutinen innerhalb eines for verwendet Schleife:

destSlice := make([]myClass, 0)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        destSlice = append(destSlice, tmpObj)
    }(myObject)
}
wg.Wait()

Gelegentlich erzeugt dieser Code fehlende oder leere Daten in destSlice oder schließt nicht alle Elemente aus sourceSlice ein. Warum könnte das passieren?

Antwort:

In Go sind alle Werte anfällig für Datenwettläufe, wenn sie gleichzeitigen Lese-/Schreibvorgängen unterliegen, einschließlich Slices. Dies liegt an der Art und Weise, wie Slice-Header (die Informationen über die Kapazität und Länge des Slice enthalten) implementiert werden.

Das Ausführen des Codes mit der Flagge -race bestätigt das Vorhandensein von Datenrennen:

go run -race play.go

Lösung:

Um Datenwettläufe zu vermeiden und gleichzeitige Sicherheit beim Anhängen an einen Slice zu gewährleisten, ein Synchronisationsprimitiv B. ein sync.Mutex, sollte verwendet werden, um das Schreiben des destSlice-Werts zu schützen:

var (
    mu        = &sync.Mutex{}
    destSlice = make([]myClass, 0)
)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        mu.Lock()
        destSlice = append(destSlice, tmpObj)
        mu.Unlock()
    }(myObject)
}
wg.Wait()

Alternativ können Sie Kanäle verwenden, um den gleichzeitigen Anhängeprozess zu erleichtern.

Das obige ist der detaillierte Inhalt vonWarum ist das Anhängen an ein Slice in gleichzeitigen Goroutinen nicht threadsicher?. 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