Heim > Backend-Entwicklung > Golang > Warum ist die Funktion „Anhängen' für den gleichzeitigen Zugriff in Go nicht threadsicher?

Warum ist die Funktion „Anhängen' für den gleichzeitigen Zugriff in Go nicht threadsicher?

Patricia Arquette
Freigeben: 2024-11-10 03:50:02
Original
365 Leute haben es durchsucht

Why is `append` function not thread-safe for concurrent access in Go?

Anhängefunktion: Nicht Thread-sicher für gleichzeitigen Zugriff

Bei der gleichzeitigen Verwendung von Goroutinen zum Anhängen von Elementen an ein Slice innerhalb einer for-Schleife treten Anomalien auf in Daten entstehen können. Fehlende oder leere Daten können im resultierenden Slice erscheinen, was auf mögliche Datenrennen hinweist.

Dies liegt daran, dass in Go kein Wert von Natur aus sicher für gleichzeitiges Lesen und Schreiben ist. Slices, die durch Slice-Header dargestellt werden, bilden keine Ausnahme. Der bereitgestellte Code weist Datenrennen aufgrund des gleichzeitigen Zugriffs auf:

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()
Nach dem Login kopieren

Um das Vorhandensein von Datenrennen zu überprüfen, führen Sie den folgenden Befehl aus:

go run -race play.go
Nach dem Login kopieren

Die Ausgabe macht Sie auf Datenrennen aufmerksam :

WARNING: DATA RACE
...
Nach dem Login kopieren

Parallelitätsprobleme lösen

An Um dieses Problem zu beheben, schützen Sie den Schreibzugriff auf das destSlice, indem Sie einen sync.Mutex verwenden:

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()
Nach dem Login kopieren

Alternativ können Sie einen Kanal verwenden, um die Anhänge asynchron zu verarbeiten:

var (
    appendChan = make(chan myClass)
    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
        appendChan <- tmpObj
    }(myObject)
}
go func() {
    for {
        tmpObj := <-appendChan
        destSlice = append(destSlice, tmpObj)
    }
}()
wg.Wait()
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonWarum ist die Funktion „Anhängen' für den gleichzeitigen Zugriff in Go nicht threadsicher?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
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
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage