Maison  >  Article  >  développement back-end  >  Parlons de Barrier in Golang

Parlons de Barrier in Golang

PHPz
PHPzoriginal
2023-04-11 09:10:37882parcourir

Lors de l'écriture de code simultané, il est souvent nécessaire d'assurer la synchronisation entre plusieurs goroutines et jetons ou verrous mutuels pour éviter la concurrence des données et les conditions de concurrence. Le langage Go fournit certains mécanismes pour réaliser ces synchronisations via les packages chan et sync, mais parfois ils ne sont pas assez flexibles et nécessitent des méthodes de synchronisation plus avancées. Dans ce cas, des barrières doivent être utilisées.

Une barrière est une primitive de synchronisation qui permet d'attendre qu'un groupe de goroutines termine une opération en même temps avant de passer à l'opération suivante. Il s'agit d'un mécanisme de synchronisation très courant. Golang fournit également un mécanisme pour mettre en œuvre des barrières, à savoir « Barrier ».

Le principe de la barrière est de diviser un groupe de goroutines en deux phases, la première phase est arrêtée une fois que chaque goroutine a terminé sa propre tâche et attend que les autres goroutines terminent, la deuxième phase est lorsque toutes les goroutines se sont arrêtées et se sont installées. les uns les autres Lorsqu'ils sont signalés, tous les goroutines reprennent leur exécution en même temps.

Golang fournit le type "WaitGroup" dans le package de synchronisation. Utilisez la méthode Add pour ajouter le nombre de goroutines en attente. La méthode Done est utilisée pour réduire un compteur au WaitGroup après que chaque goroutine ait terminé la tâche. bloque jusqu'à ce que le compteur tombe à zéro, c'est-à-dire que toutes les goroutines ont terminé leurs tâches avant de passer à l'étape suivante.

Cependant, WaitGroup a un inconvénient : il ne peut attendre qu'un nombre fixe de goroutines se terminent. Lorsque de nouvelles goroutines rejoignent, nous ne pouvons pas l'utiliser. À l’heure actuelle, nous pouvons utiliser Barrier pour résoudre ce problème.

Barrier peut être utilisé avec n'importe quel nombre de goroutines et peut effectuer toutes les opérations spécifiées à la fin de chaque étape. Il contient un compteur indiquant combien de goroutines attendent la fin de l'ensemble des opérations, et une fonction à exécuter à la fin de chaque étape.

"Un groupe de threads en attente" dans Golang peut être implémenté en utilisant le "WaitGroup" du package de synchronisation :

var wg sync.WaitGroup

func worker() {
    defer wg.Done()
    // 执行自己的任务
}

func main() {
    for i := 0; i < n; i++ {
        wg.Add(1)
        go worker()
    }
    // 等待所有线程完成
    wg.Wait()
}

Maintenant, nous utilisons "Barrier" pour créer un exemple de goroutine qui peut être appliqué aux modifications :

package main

import "fmt"
import "sync"

func main() {
    b := sync.NewCond(&sync.Mutex{})
    done := make(chan bool)

    worker := func(id int) {
        defer func() {
            fmt.Printf("Worker %d done\n", id)
            done <- true
        }()
        fmt.Printf("Worker %d processing\n", id)
        b.L.Lock()
        b.Wait() // 等待阻塞直到b.Broadcast()被执行
        b.L.Unlock()
        fmt.Printf("Worker %d resumed\n", id)
    }

    go func() {
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go worker(i)
        }
    }()

    go func() {
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go worker(i)
        }
    }()

    go func() {
        wg.Wait()
        b.Broadcast()
    }()

    for i := 0; i < 20; i++ {
        <-done
    }
    fmt.Printf("All workers done\n")
}

Cet exemple crée 20 goroutines, qui sont divisées en deux étapes. La première étape attend que chaque goroutine termine sa propre tâche, et la deuxième étape attend que toutes les goroutines soient terminées avant d'exécuter l'opération.

Lorsque deux groupes de goroutines sont créés, l'une des goroutines appelle "Attendez" et bloque jusqu'à ce que toutes les goroutines terminent leurs tâches. Lorsque les autres threads ont terminé leurs tâches, le blocage est libéré et des signaux sont envoyés à toutes les goroutines en utilisant « Broadcast » pour continuer l'étape suivante.

En bref, Golang's Barrier vous permet de synchroniser des opérations simultanées à un niveau plus avancé et de rendre votre code plus robuste et fiable.

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