Maison >développement back-end >Golang >Comment éviter les blocages dans Go lorsque vous utilisez WaitGroup et un canal avec un tampon limité ?
Impasse dans Go avec WaitGroup et Channel
Dans Go, une impasse se produit lorsque deux goroutines ou plus attendent indéfiniment que l'autre termine. Dans cet exemple, nous explorerons un problème de blocage causé par un tampon de canal insuffisant et une synchronisation incorrecte des goroutines à l'aide d'un WaitGroup.
Le code
<code class="go">package main import "fmt" import "sync" func main() { ch := make(chan []int, 4) var m []int var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func() { defer wg.Done() ch <- m return }() } wg.Wait() for c := range ch { fmt.Printf("c is %v", c) } }</code>
Le problème
Le code tente d'envoyer 5 valeurs sur un canal tamponné de taille 4. Cependant, lorsque le canal est plein, il se bloque jusqu'à ce qu'un récepteur devienne disponible. Puisque toutes les goroutines qui envoient sont terminées, aucune n'est disponible pour recevoir du canal.
De plus, la goroutine qui s'étend sur le canal (pour c := range ch) reste également bloquée indéfiniment car elle attend plus de valeurs pour arriver dans le canal même si aucun autre message n'est envoyé. Cela crée une impasse dans laquelle les expéditeurs et les destinataires s'attendent les uns les autres.
Solution 1 : Augmentez la mémoire tampon du canal et fermez-la
Une solution pour éviter l'impasse consiste à augmentez la taille du tampon du canal à une valeur supérieure ou égale au nombre de goroutines d'envoi. De plus, le canal doit être fermé une fois tous les envois terminés, indiquant qu'aucune autre valeur ne sera reçue.
<code class="go">ch := make(chan []int, 5) ... wg.Wait() close(ch)</code>
Solution 2 : Effectuer Done() dans la réception de Goroutine
Une autre solution consiste à exécuter Done() dans la goroutine de réception plutôt que dans la fonction principale. Ce faisant, le WaitGroup ne sera pas décrémenté tant que la valeur n'aura pas été reçue et consommée par la goroutine :
<code class="go">func main() { ch := make(chan []int, 4) var m []int var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func() { ch <- m return }() } go func() { for c := range ch { fmt.Printf("c is %v\n", c) wg.Done() } }() wg.Wait() }</code>
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!