Maison >développement back-end >Golang >Compétences en programmation simultanée : utilisation avancée de Go WaitGroup

Compétences en programmation simultanée : utilisation avancée de Go WaitGroup

王林
王林original
2023-09-28 21:52:45943parcourir

并发编程技巧:Go WaitGroup的高级用法

Conseils de programmation simultanée : utilisation avancée de Go WaitGroup

Dans la programmation simultanée, coordonner et gérer l'exécution de plusieurs tâches simultanées est une tâche importante. Le langage Go fournit une primitive de concurrence très pratique - WaitGroup, qui peut nous aider à implémenter le contrôle de concurrence avec élégance. Cet article présentera l'utilisation de base de WaitGroup et se concentrera sur son utilisation avancée, en utilisant des exemples de code spécifiques pour aider les lecteurs à mieux le comprendre et l'appliquer.

WaitGroup est une primitive de concurrence intégrée au langage Go, qui peut nous aider à attendre la fin de tâches simultanées. Il propose trois méthodes : Ajouter, Terminer et Attendre. La méthode Add est utilisée pour définir le nombre de tâches en attente, la méthode Done est utilisée pour réduire le nombre de tâches en attente et la méthode Wait est utilisée pour bloquer la coroutine actuelle jusqu'à ce que toutes les tâches en attente soient terminées.

Voici un exemple simple montrant l'utilisation de base de WaitGroup :

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(num int) {
            defer wg.Done()

            time.Sleep(time.Second)
            fmt.Println("Task", num, "done")
        }(i)
    }

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

Dans le code ci-dessus, nous créons un objet WaitGroup wg et créons 5 tâches simultanées via une boucle. Lors de l'exécution de chaque tâche, nous utilisons la méthode Add pour augmenter le nombre de tâches en attente, et à la fin de la tâche, nous utilisons la méthode Done pour réduire le nombre de tâches en attente. Enfin, nous appelons la méthode Wait pour bloquer la coroutine principale jusqu'à ce que toutes les tâches en attente soient terminées.

En plus de l'utilisation de base, WaitGroup propose également une utilisation avancée, qui permet de contrôler l'exécution de tâches simultanées de manière plus flexible. Ci-dessous, nous présenterons en détail plusieurs utilisations avancées couramment utilisées.

  1. Exécuter un ensemble de tâches et définir le nombre maximum de simultanéités

Si nous devons exécuter un ensemble de tâches en même temps, mais que nous voulons limiter le nombre maximum de simultanéités, nous pouvons utiliser un canal tampon combiné avec WaitGroup pour y parvenir. Le code ci-dessous montre comment exécuter un ensemble de tâches en même temps, mais n'autorise qu'un maximum de 3 tâches à s'exécuter simultanément :

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    maxConcurrency := 3
    tasks := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

    sem := make(chan struct{}, maxConcurrency)

    for _, task := range tasks {
        wg.Add(1)
        sem <- struct{}{} // 获取令牌,控制最大并发数

        go func(num int) {
            defer wg.Done()

            time.Sleep(time.Second)
            fmt.Println("Task", num, "done")

            <-sem // 释放令牌,允许新的任务执行
        }(task)
    }

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

Dans le code ci-dessus, nous créons un canal sem tamponné et définissons sa taille au nombre maximum. des concurrences. Avant le début de chaque tâche, nous obtenons un jeton via l'instruction sem <- struct{}{}. Lorsque la tâche est terminée, nous utilisons l'instruction <-sem pour libérer le jeton. En contrôlant l'acquisition et la libération des jetons, nous pouvons limiter le nombre maximum de simultanéités.

  1. Timeout contrôle l'exécution des tâches simultanées

Parfois, nous souhaitons contrôler le temps d'exécution des tâches simultanées et mettre fin à l'exécution de la tâche lorsqu'elle expire. En utilisant des canaux tamponnés et des minuteries, nous pouvons facilement implémenter cette fonctionnalité. Le code suivant montre comment définir le délai d'expiration d'une tâche simultanée à 3 secondes :

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    tasks := []int{1, 2, 3, 4, 5, 6, 7}

    timeout := 3 * time.Second
    done := make(chan struct{})

    for _, task := range tasks {
        wg.Add(1)

        go func(num int) {
            defer wg.Done()

            // 模拟任务执行时间不定
            time.Sleep(time.Duration(num) * time.Second)
            fmt.Println("Task", num, "done")

            // 判断任务是否超时
            select {
            case <-done:
                // 任务在超时前完成,正常退出
                return
            default:
                // 任务超时,向通道发送信号
                close(done)
            }
        }(task)
    }



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

Dans le code ci-dessus, nous créons un canal terminé et déterminons si le canal est fermé pendant l'exécution de la tâche pour déterminer si la tâche expire. Lorsqu'une tâche est terminée, nous utilisons l'instruction close(done) pour envoyer un signal au canal terminé pour indiquer que la tâche a expiré. Choisissez différentes branches via des instructions select pour gérer différentes situations.

Grâce à l'exemple de code ci-dessus, nous pouvons voir que l'utilisation avancée de WaitGroup est très pratique dans la programmation simultanée réelle. En maîtrisant ces techniques, nous pouvons mieux contrôler l'exécution des tâches concurrentes et améliorer les performances et la maintenabilité du code. J'espère que les lecteurs pourront avoir une compréhension approfondie de l'utilisation de WaitGroup grâce à l'introduction et à l'exemple de code de cet article, puis l'appliquer à des projets réels.

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