首頁  >  文章  >  後端開發  >  並發 Go 程式中應該將 `wg.Add()` 放在哪裡?

並發 Go 程式中應該將 `wg.Add()` 放在哪裡?

Susan Sarandon
Susan Sarandon原創
2024-10-26 13:28:02924瀏覽

 Where Should You Place `wg.Add()` in Concurrent Go Programs?

理解 wg.Add() 的放置

在並發 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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn