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

Sep 28, 2023 pm 09:52 PM
go 并发编程 waitgroup

并发编程技巧: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")
}
Copier après la connexion

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")
}
Copier après la connexion

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")
}
Copier après la connexion

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 de ce site Web
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

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Conception sécurisée de structures de données en programmation simultanée C++ ? Conception sécurisée de structures de données en programmation simultanée C++ ? Jun 05, 2024 am 11:00 AM

Dans la programmation simultanée C++, la conception sécurisée des structures de données est cruciale : Section critique : utilisez un verrou mutex pour créer un bloc de code qui permet à un seul thread de s'exécuter en même temps. Verrouillage en lecture-écriture : permet à plusieurs threads de lire en même temps, mais à un seul thread d'écrire en même temps. Structures de données sans verrouillage : utilisez des opérations atomiques pour assurer la sécurité de la concurrence sans verrous. Cas pratique : File d'attente thread-safe : utilisez les sections critiques pour protéger les opérations de file d'attente et assurer la sécurité des threads.

Comment envoyer des messages Go WebSocket ? Comment envoyer des messages Go WebSocket ? Jun 03, 2024 pm 04:53 PM

Dans Go, les messages WebSocket peuvent être envoyés à l'aide du package gorilla/websocket. Étapes spécifiques : Établissez une connexion WebSocket. Envoyer un message texte : appelez WriteMessage(websocket.TextMessage,[]byte("message")). Envoyez un message binaire : appelez WriteMessage(websocket.BinaryMessage,[]byte{1,2,3}).

La différence entre la langue Golang et Go La différence entre la langue Golang et Go May 31, 2024 pm 08:10 PM

Go et le langage Go sont des entités différentes avec des caractéristiques différentes. Go (également connu sous le nom de Golang) est connu pour sa concurrence, sa vitesse de compilation rapide, sa gestion de la mémoire et ses avantages multiplateformes. Les inconvénients du langage Go incluent un écosystème moins riche que les autres langages, une syntaxe plus stricte et un manque de typage dynamique.

Comment faire correspondre les horodatages à l'aide d'expressions régulières dans Go ? Comment faire correspondre les horodatages à l'aide d'expressions régulières dans Go ? Jun 02, 2024 am 09:00 AM

Dans Go, vous pouvez utiliser des expressions régulières pour faire correspondre les horodatages : compilez une chaîne d'expression régulière, telle que celle utilisée pour faire correspondre les horodatages ISO8601 : ^\d{4}-\d{2}-\d{2}T \d{ 2}:\d{2}:\d{2}(\.\d+)?(Z|[+-][0-9]{2}:[0-9]{2})$ . Utilisez la fonction regexp.MatchString pour vérifier si une chaîne correspond à une expression régulière.

Explication détaillée des primitives de synchronisation dans la programmation simultanée C++ Explication détaillée des primitives de synchronisation dans la programmation simultanée C++ May 31, 2024 pm 10:01 PM

Dans la programmation multithread C++, le rôle des primitives de synchronisation est de garantir l'exactitude de l'accès de plusieurs threads aux ressources partagées. Elle comprend : Mutex (Mutex) : protège les ressources partagées et empêche l'accès simultané. Variable de condition (ConditionVariable) : thread Attendre une réponse spécifique ; conditions à remplir avant de poursuivre l’exécution de l’opération atomique : s’assurer que l’opération s’exécute de manière ininterrompue.

Comment éviter les fuites de mémoire dans l'optimisation des performances techniques de Golang ? Comment éviter les fuites de mémoire dans l'optimisation des performances techniques de Golang ? Jun 04, 2024 pm 12:27 PM

Les fuites de mémoire peuvent entraîner une augmentation continue de la mémoire du programme Go en : fermant les ressources qui ne sont plus utilisées, telles que les fichiers, les connexions réseau et les connexions à la base de données. Utilisez des références faibles pour éviter les fuites de mémoire et ciblez les objets pour le garbage collection lorsqu'ils ne sont plus fortement référencés. En utilisant go coroutine, la mémoire de la pile de coroutines sera automatiquement libérée à la sortie pour éviter les fuites de mémoire.

Choses à noter lorsque les fonctions Golang reçoivent des paramètres de carte Choses à noter lorsque les fonctions Golang reçoivent des paramètres de carte Jun 04, 2024 am 10:31 AM

Lors du passage d'une carte à une fonction dans Go, une copie sera créée par défaut et les modifications apportées à la copie n'affecteront pas la carte d'origine. Si vous devez modifier la carte originale, vous pouvez la passer via un pointeur. Les cartes vides doivent être manipulées avec précaution, car ce sont techniquement des pointeurs nuls, et passer une carte vide à une fonction qui attend une carte non vide provoquera une erreur.

Comment utiliser le wrapper d'erreur de Golang ? Comment utiliser le wrapper d'erreur de Golang ? Jun 03, 2024 pm 04:08 PM

Dans Golang, les wrappers d'erreurs vous permettent de créer de nouvelles erreurs en ajoutant des informations contextuelles à l'erreur d'origine. Cela peut être utilisé pour unifier les types d'erreurs générées par différentes bibliothèques ou composants, simplifiant ainsi le débogage et la gestion des erreurs. Les étapes sont les suivantes : Utilisez la fonction error.Wrap pour envelopper les erreurs d'origine dans de nouvelles erreurs. La nouvelle erreur contient des informations contextuelles de l'erreur d'origine. Utilisez fmt.Printf pour générer des erreurs encapsulées, offrant ainsi plus de contexte et de possibilités d'action. Lors de la gestion de différents types d’erreurs, utilisez la fonction erreurs.Wrap pour unifier les types d’erreurs.

See all articles