Maison >développement back-end >Golang >Pourquoi l'ajout aux tranches dans Go est-il dangereux pour les threads ?
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()
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 ==================
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()
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!