Dans les programmes Go simultanés, le type sync.WaitGroup sert de primitive de synchronisation pour coordonner l'achèvement des tâches. Lorsque vous travaillez avec un WaitGroup, l'endroit où vous placez l'appel wg.Add() est essentiel pour garantir un comportement d'attente correct.
Considérez le code suivant :
<code class="go">var wg sync.WaitGroup var v int32 = 0 for i := 0; i < 100; i++ { go func() { wg.Add(1) // wrong place atomic.AddInt32(&v, 1) wg.Done() }() } wg.Wait() fmt.Println(v)</code>
Ce code vise à paralléliser un série de tâches et incrémenter une variable partagée v simultanément. Cependant, le résultat donne souvent des valeurs inférieures à 100. Le problème réside dans le placement de wg.Add(1) dans la goroutine anonyme.
En plaçant wg.Add(1) dans la goroutine, le principal goroutine peut reprendre l'exécution avant que wg.Done() ne soit appelé. Cela peut se produire car le modèle de concurrence permet à la fois à l'appel wg.Add(1) et à l'appel wg.Done() de s'exécuter simultanément, ce qui pourrait entraîner une fin prématurée de l'attente dans la goroutine principale.
Pour résoudre ce problème problème, l'appel wg.Add(1) doit être déplacé en dehors de la goroutine, comme indiqué ci-dessous :
<code class="go">var wg sync.WaitGroup var v int32 = 0 for i := 0; i < 100; i++ { wg.Add(1) go func() { atomic.AddInt32(&v, 1) wg.Done() }() } wg.Wait() fmt.Println(v)</code>
En déplaçant wg.Add(1) en dehors de la goroutine, nous nous assurons que la goroutine principale bloquera sur l'appel wg.Wait() jusqu'à ce que toutes les goroutines soient terminées et appelées wg.Done(). Cela garantit que la valeur finale de v est exacte.
En règle générale, il est recommandé de toujours appeler wg.Add() avant de lancer une goroutine qui appellera wg.Done(). Cela garantit un comportement d'attente approprié et élimine toute condition de concurrence pouvant survenir.
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!