Maison >développement back-end >Golang >Comment éviter les conditions de concurrence lors de l'utilisation de sync.Cond pour l'attente conditionnelle ?

Comment éviter les conditions de concurrence lors de l'utilisation de sync.Cond pour l'attente conditionnelle ?

Susan Sarandon
Susan Sarandonoriginal
2024-11-10 14:21:02906parcourir

How to Avoid Race Conditions When Using sync.Cond for Conditional Waiting?

Utiliser correctement sync.Cond pour l'attente conditionnelle

En explorant la fonctionnalité de sync.Cond, il est devenu évident qu'une condition de concurrence pourrait survenir entre le verrouillage du sync.Mutex et l'invocation de cond.Wait. Pour démontrer cela, un retard artificiel a été introduit dans la goroutine principale, simulant la condition de concurrence :

package main

import (
    "sync"
    "time"
)

func main() {
    var m sync.Mutex
    var c = sync.NewCond(&m)

    go func() {
        time.Sleep(1 * time.Second)
        c.Broadcast()
    }()

    m.Lock()
    time.Sleep(2 * time.Second)
    c.Wait()
}

L'exécution de ce code entraîne une panique de blocage due au fait que la goroutine attend une condition qui n'a pas encore été signalée. .

Résoudre les conditions de concurrence

La bonne approche pour éviter cette condition de concurrence est de garantir que le sync.Mutex est verrouillé avant d'appeler cond.Wait. Cela empêche d'autres goroutines de modifier les données partagées pendant que la goroutine actuelle attend une condition :

package main

import (
    "sync"
    "time"
)

func main() {
    var m sync.Mutex
    var c = sync.NewCond(&m)

    go func() {
        time.Sleep(1 * time.Second)
        m.Lock()
        c.Broadcast()
        m.Unlock()
    }()

    m.Lock()
    c.Wait()
    m.Unlock()
}

Constructions de synchronisation alternatives

Alors que sync.Cond peut être utile dans les scénarios où plusieurs goroutines attendent qu'une ressource partagée soit disponible, il est important d'envisager des primitives de synchronisation alternatives. Par exemple, si vous avez une relation individuelle entre un écrivain et un lecteur, une synchronisation.Mutex peut suffire pour la communication :

var sharedRsc = make(map[string]interface{})

func main() {
    m := sync.Mutex{}
    go func() {
        m.Lock()
        sharedRsc["rsc1"] = "foo"
        m.Unlock()
    }()

    m.Lock()
    fmt.Println(sharedRsc["rsc1"])
    m.Unlock()
}

Dans les cas où plusieurs lecteurs sont impliqués, les canaux offrent une et évolutive pour transmettre 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!

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