Maison >développement back-end >Golang >Comment puis-je empêcher les courses de données lors de la lecture et de l'écriture simultanées de Go Structs ?

Comment puis-je empêcher les courses de données lors de la lecture et de l'écriture simultanées de Go Structs ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-12-25 04:21:09542parcourir

How Can I Prevent Data Races When Concurrently Reading and Writing Go Structs?

Lecture et écriture simultanées de structures Go sans verrouillage explicite

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.

Accès simultané aux structures

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.

Courses de données dans les structures

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.

Résoudre les courses aux données dans les structures

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!

Déclaration:
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