Maison > développement back-end > Golang > Pourquoi l'ajout aux tranches dans Go est-il dangereux pour les threads ?

Pourquoi l'ajout aux tranches dans Go est-il dangereux pour les threads ?

Susan Sarandon
Libérer: 2024-11-09 17:30:02
original
318 Les gens l'ont consulté

Why is appending to slices in Go thread-unsafe?

Pourquoi l'ajout à des tranches peut être dangereux pour les threads

Lorsque plusieurs goroutines tentent d'ajouter des données à une tranche simultanément, une condition de concurrence critique entre les données peut se produire. En effet, les tranches dans Go ne sont pas thread-safe, ce qui signifie que plusieurs goroutines peuvent accéder et modifier simultanément le même en-tête de tranche, ce qui peut potentiellement provoquer une corruption des données.

Illustration de la course aux données

Considérez le code suivant :

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()
Copier après la connexion

Dans ce code, plusieurs goroutines s'ajoutent simultanément à la tranche destSlice. Cela peut entraîner des données manquantes ou vides dans la tranche résultante, car les goroutines peuvent entrelacer leurs opérations et écraser les modifications les unes des autres.

Vérification des courses de données avec l'option "-race"

L'exécution du code avec l'option "-race" générera un avertissement pour chaque course aux données détectée. Le résultat suivant illustre les conditions de concurrence des données dans le code fourni :

==================
WARNING: DATA RACE
Read at 0x00c420074000 by goroutine 6:
  main.main.func1()
      /home/icza/gows/src/play/play.go:20 +0x69

Previous write at 0x00c420074000 by goroutine 5:
  main.main.func1()
      /home/icza/gows/src/play/play.go:20 +0x106

Goroutine 6 (running) created at:
  main.main()
      /home/icza/gows/src/play/play.go:21 +0x1cb

Goroutine 5 (running) created at:
  main.main()
      /home/icza/gows/src/play/play.go:21 +0x1cb
==================
Copier après la connexion

Solution : Utilisation d'un mutex pour la synchronisation

Pour garantir des ajouts simultanés sécurisés par les threads, vous peut utiliser un mutex pour protéger l'en-tête de la tranche destSlice. Le code modifié suivant le démontre :

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()
Copier après la connexion

En acquérant le mutex avant chaque opération d'ajout, vous empêchez plusieurs goroutines de modifier simultanément l'en-tête de tranche, garantissant l'intégrité des données et éliminant la condition de concurrence critique des données.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal