Maison  >  Article  >  développement back-end  >  Combinaison efficace de Golang WaitGroup et du pool de coroutines

Combinaison efficace de Golang WaitGroup et du pool de coroutines

王林
王林original
2023-09-28 17:22:491214parcourir

Golang WaitGroup和协程池的高效结合

La combinaison efficace de Golang WaitGroup et du pool de coroutines nécessite des exemples de code spécifiques

Introduction :
Le langage Go est un langage qui met l'accent sur la programmation simultanée et permet une exécution simultanée efficace via la coroutine (goroutine). Dans certains scénarios où plusieurs tâches doivent être exécutées simultanément, la combinaison de WaitGroup et du pool de coroutines peut améliorer efficacement l'efficacité d'exécution et l'utilisation des ressources du programme. Cet article expliquera comment utiliser WaitGroup et le pool de coroutines dans Golang pour obtenir une programmation simultanée efficace et fournira des exemples de code spécifiques.

1. Introduction à WaitGroup
WaitGroup est un outil en langage Go utilisé pour attendre la fin d'un groupe de coroutines. Son code source est défini comme suit :

type WaitGroup struct {
    noCopy noCopy

    // 64位的值:高32位存储计数器,低32位存储等待计数器
    // 这个变量可以被原子操作加载和存储。
    // 在64位同步原语中,它必须在64位边界对齐。
    // 是一个强制的要求。
    state1 [3]uint32
}

WaitGroup est généralement créé dans la goroutine principale, puis chaque sous-goroutine de la goroutine principale appelle la méthode Add pour augmenter le compteur, et une fois l'exécution terminée, la méthode Done est utilisé pour décrémenter le compteur. La goroutine principale peut attendre que le compteur revienne à zéro via la méthode Wait. L'exemple de code spécifique est le suivant :

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    wg.Add(3)

    go func() {
        defer wg.Done()
        fmt.Println("Task 1 executing")
    }()

    go func() {
        defer wg.Done()
        fmt.Println("Task 2 executing")
    }()

    go func() {
        defer wg.Done()
        fmt.Println("Task 3 executing")
    }()

    wg.Wait()
    fmt.Println("All tasks completed")
}

Dans l'exemple ci-dessus, nous créons un objet WaitGroup puis incrémentons le compteur en appelant la méthode Add. Ensuite, nous avons créé trois sous-goroutines. Après l'exécution de chaque goroutine, le compteur est décrémenté via la méthode Done. Enfin, la goroutine principale attend que le compteur revienne à zéro en appelant la méthode Wait. Lorsque toutes les tâches sont terminées, le programme affichera « Toutes les tâches terminées ».

2. Introduction au pool de coroutines
En programmation simultanée, le pool de goroutines est un mode couramment utilisé. En créant un nombre fixe de goroutines et en leur répartissant uniformément les tâches, vous pouvez éviter les frais généraux liés à la création et à la destruction constantes de goroutines. En langage Go, vous pouvez utiliser des canaux pour implémenter des pools de coroutines. L'exemple de code spécifique est le suivant :

package main

import (
    "fmt"
    "sync"
)

func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        fmt.Println("Worker", id, "started job", j)
        fib := fibonacci(j)
        fmt.Println("Worker", id, "finished job", j)
        results <- fib
    }
}

func fibonacci(n int) int {
    if n <= 1 {
        return n
    }

    return fibonacci(n-1) + fibonacci(n-2)
}

const numJobs = 5
const numWorkers = 3

func main() {
    jobs := make(chan int, numJobs)
    results := make(chan int, numJobs)

    var wg sync.WaitGroup
    wg.Add(numWorkers)

    for w := 1; w <= numWorkers; w++ {
        go func(id int) {
            defer wg.Done()
            worker(id, jobs, results)
        }(w)
    }

    for j := 1; j <= numJobs; j++ {
        jobs <- j
    }
    close(jobs)

    wg.Wait()

    for r := 1; r <= numJobs; r++ {
        fmt.Println(<-results)
    }
}

Dans l'exemple ci-dessus, nous avons défini la fonction de travail, qui lit les tâches en attente à partir du canal des tâches, puis exécute les tâches et envoie les résultats au canal des résultats. Nous avons créé un canal d'emplois et un canal de résultats pour mettre en œuvre la fonction du pool de coroutines en répartissant les tâches et en obtenant des résultats.

Dans la fonction principale, nous utilisons WaitGroup pour attendre que tous les travailleurs (goroutines) terminent l'exécution de la tâche. Ensuite, nous envoyons les tâches à exécuter vers le canal jobs et fermons le canal après exécution. Enfin, nous obtenons les résultats du calcul du canal de résultats et les publions.

3. Un cas de combinaison efficace de WaitGroup et du pool de coroutines
Ensuite, nous combinerons les deux concepts ci-dessus pour présenter comment utiliser efficacement WaitGroup et le pool de coroutines pour implémenter la programmation simultanée. L'exemple de code spécifique est le suivant :

package main

import (
    "fmt"
    "sync"
)

func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        fmt.Println("Worker", id, "started job", j)
        fib := fibonacci(j)
        fmt.Println("Worker", id, "finished job", j)
        results <- fib
    }
}

func fibonacci(n int) int {
    if n <= 1 {
        return n
    }

    return fibonacci(n-1) + fibonacci(n-2)
}

const numJobs = 5
const numWorkers = 3

func main() {
    var wg sync.WaitGroup
    wg.Add(numWorkers)

    jobs := make(chan int, numJobs)
    results := make(chan int, numJobs)

    for w := 1; w <= numWorkers; w++ {
        go func(id int) {
            defer wg.Done()
            worker(id, jobs, results)
        }(w)
    }

    for j := 1; j <= numJobs; j++ {
        jobs <- j
    }
    close(jobs)

    go func() {
        wg.Wait()
        close(results)
    }()

    for r := range results {
        fmt.Println(r)
    }
}

Dans l'exemple ci-dessus, nous avons créé un objet WaitGroup et incrémenté le compteur en appelant la méthode Add. Ensuite, nous avons créé une chaîne d'emplois et une chaîne de résultats pour répartir les tâches et obtenir des résultats. Nous créons un nombre fixe de travailleurs (goroutines) et utilisons la méthode Wait pour attendre qu'ils terminent leurs tâches.

Dans la fonction principale, nous envoyons les tâches à exécuter au canal jobs et fermons le canal après exécution. Nous démarrons ensuite une coroutine pour attendre que tous les travailleurs terminent leurs tâches et fermons le canal des résultats une fois terminés. Enfin, nous extrayons les résultats du calcul en les récupérant du canal des résultats.

Conclusion :
En combinant WaitGroup et le pool de coroutines, nous pouvons réaliser efficacement une programmation simultanée. En utilisant un WaitGroup pour attendre la fin de l'exécution d'un groupe de goroutines, vous pouvez vous assurer que la goroutine principale continue de s'exécuter une fois toutes les tâches terminées. En utilisant le pool de coroutines, nous pouvons éviter les frais généraux liés à la création et à la destruction fréquentes de goroutines et améliorer l'efficacité d'exécution et l'utilisation des ressources du programme.

Le calcul de la séquence de Fibonacci dans l'exemple de code n'est qu'un exemple de démonstration et peut être remplacé par d'autres tâches en fonction des besoins spécifiques des applications réelles. Grâce à WaitGroup et au pool de coroutines, nous pouvons mieux contrôler le nombre de tâches exécutées simultanément et utiliser efficacement les ressources informatiques.

Bien que le langage Go fournisse de riches outils et fonctionnalités de programmation simultanée, vous devez toujours être prudent lorsque vous les utilisez. Une utilisation appropriée de WaitGroup et du pool de coroutines peut nous aider à mieux gérer et planifier les goroutines et à réaliser une programmation simultanée efficace.

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