在並發 Go 程式中,sync.WaitGroup 類型充當同步原語來協調任務的完成。使用 WaitGroup 時,放置 wg.Add() 呼叫對於確保正確的等待行為至關重要。
考慮以下程式碼:
<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>
此程式碼旨在並行化一系列任務並同時增加共享變數 v。然而,輸出結果通常會小於 100。問題在於匿名 goroutine 中 wg.Add(1) 的放置。
透過將 wg.Add(1) 放置在 goroutine 中,主函數Goroutine 可以在呼叫 wg.Done() 之前恢復執行。發生這種情況的原因是並發模型允許 wg.Add(1) 呼叫和 wg.Done() 呼叫同時執行,可能會導致主 Goroutine 中的等待提前終止。
解決此問題問題,wg.Add(1)呼叫應該移到goroutine之外,如下所示:
<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>
透過將wg.Add(1)移到goroutine之外,我們確保主goroutine會阻塞在wg.Wait() 呼叫上,直到所有goroutine 完成並呼叫wg.Done()。這保證了 v 的最終值是準確的。
作為一般實踐,建議在啟動將調用 wg.Done() 的 goroutine 之前始終調用 wg.Add()。這可確保正確的等待行為並消除可能出現的任何競爭條件。
以上是並發 Go 程式中應該將 `wg.Add()` 放在哪裡?的詳細內容。更多資訊請關注PHP中文網其他相關文章!