首頁 >後端開發 >Golang >為什麼 wg.Add() 放置對於保證 Go 中的同步至關重要?

為什麼 wg.Add() 放置對於保證 Go 中的同步至關重要?

DDD
DDD原創
2024-10-27 20:40:03749瀏覽

Why is wg.Add() Placement Crucial for Guaranteed Synchronization in Go?

為保證同步而定位wg.Add()

問題

在下面的Go 程式碼中,變數v 通常小於預期,因為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>

解決方案

wg.Add() 應始終在啟動相應的Goroutine 之前調用,以確保主Goroutine 阻塞,直到所有goroutine 已執行wg.Done().

<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() 放在goroutine 內部時,不能保證主goroutine 會阻塞,直到所有goroutine 完成。這是因為 goroutine 是並發運行的,執行順序是不確定的。

透過將wg.Add() 放在goroutine 之前,我們可以確保主goroutine 在到達之前調用wg.Add() 100 次wg.Wait().這可以確保主goroutine 阻塞,直到所有100個goroutine 都呼叫了wg.Done(),導致v 總是等於100。

最佳實踐

使用sync.WaitGroup 時,請遵循這些指南:

  • 在使用go 啟動新的goroutine 之前,先在「原始」goroutine中呼叫wg.Add()。
  • 使用 defer 語句呼叫 wg.Done() 以確保即使 goroutine 發生恐慌,它也會被呼叫。
  • 將 wg 傳遞給其他函數時,傳遞一個指標以避免建立 wg 結構的副本。

以上是為什麼 wg.Add() 放置對於保證 Go 中的同步至關重要?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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