L'accès simultané aux données partagées dans Go peut être une source d'erreurs potentielles, telles que des courses de données. Lorsque l'accès à une structure de données est simultané, c'est-à-dire que plusieurs goroutines peuvent y accéder en même temps, il est crucial de s'assurer que les données sont lues et écrites de manière synchronisée pour éviter les incohérences.
Considérez les métadonnées de la structure Go suivantes :
type Metadata struct { mu sync.RWMutex // ? key bool }
Comme nous pouvons le voir, les métadonnées struct contient une clé de champ de type bool et un autre champ mu de type sync.RWMutex, qui est une implémentation d'un verrou en lecture-écriture.
Si nous créons un instance de métadonnées et permettre à plusieurs goroutines de lire et d'écrire simultanément ses champs, nous pourrions rencontrer des courses de données. Une course aux données se produit lorsque plusieurs goroutines accèdent simultanément aux mêmes données et qu'au moins l'un d'entre eux effectue une opération d'écriture.
Le code suivant démontre un accès simultané en lecture et en écriture à la structure des métadonnées sans verrouillage explicite :
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 {} }
Dans ce code, nous créons une goroutine qui lit et écrit le champ clé simultanément. Nous utilisons une instruction select pour bloquer la goroutine principale, permettant aux goroutines simultanées de s'exécuter. En utilisant la commande go run -race pour exécuter le programme, nous recevrons un avertissement indiquant une DATA RACE.
Cependant, le programme continue de s'exécuter sans planter. En effet, le runtime Go intègre une vérification de concurrence, mais il ne garantit pas une exécution sûre. Dans ce cas, la course aux données peut conduire à un comportement indéfini et à des résultats incorrects.
Pour éviter les courses aux données lors de la lecture et de l'écriture simultanées dans des structures, nous devons utiliser les méthodes appropriées. mécanismes de verrouillage. Une solution consiste à utiliser des mutex, comme démontré dans le code suivant :
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 {} }
Dans ce code, nous avons ajouté un verrou en lecture-écriture à la structure des métadonnées et utilisons mu.Lock() et mu. Unlock() pour synchroniser l'accès au champ clé. L'exécution du programme avec go run -race ne générera plus d'avertissements, indiquant qu'il n'y a pas de courses de 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!