首頁 > 後端開發 > Golang > 為什麼在 Go 中按值傳遞 WaitGroup 會導致死鎖,如何解決?

為什麼在 Go 中按值傳遞 WaitGroup 會導致死鎖,如何解決?

Linda Hamilton
發布: 2024-10-28 18:56:29
原創
615 人瀏覽過

Why does passing a WaitGroup by value in Go lead to a deadlock, and how can it be resolved?

Go Channels 的死鎖:變數作用域的問題

在 Golang 程式中,Channel 促進了 goroutine 之間的通訊。然而,誤用通道可能會導致死鎖,如下面的程式碼所示:

<br>package main<p>import (</p><pre class="brush:php;toolbar:false">"fmt"
"sync"
登入後複製

)

func push(c chan int, wgsync.WaitGroup) {

for i := 0; i < 5; i++ {
    c <- i
}
wg.Done()
登入後複製
登入後複製

}

func pull(c chan 是🎜>

}
for i := 0; i < 5; i++ {
    result, ok := <-c
    fmt.Println(result, ok)
}
wg.Done()
登入後複製
登入後複製

func main() {

}
var wg sync.WaitGroup
wg.Add(2)
c := make(chan int)

go push(c, wg)
go pull(c, wg)

wg.Wait() // Block the main thread until goroutines complete
登入後複製


執行此程式時,您可能會遇到出現以下錯誤:

要理解為什麼會發生這種死鎖,讓我們深入研究一下代碼:
fatal error: all goroutines are asleep - deadlock!
登入後複製

main 創建一個WaitGroup、一個通道c 以及用於推拉的goroutine
  • push 和pull 函數使用WaitGroup 來同步它們的執行。
  • push 函數在迴圈中向 c 發送值,並透過呼叫 wg.Done() 來表示其完成。
  • pull 函數從 c 接收值並列印它們。它還使用 wg.Done() 發出完成訊號。
  • 問題在於如何將 WaitGroup 傳給 goroutine。當傳遞的值不帶與號 (&) 時,它是按值傳遞,而不是按引用傳遞。在這種情況下,將為每個 goroutine 建立一個 WaitGroup 的副本。

因此,當每個 goroutine 呼叫 wg.Done() 時,它會修改其本地的 WaitGroup 副本。由於主執行緒會一直等待,直到 wg 指示所有 Goroutine 都已完成,因此它會無限期地等待,因為兩個 Goroutine 都不會更新原始的 WaitGroup。這會導致死鎖。

要解決此問題,我們需要透過引用傳遞 WaitGroup。這可以確保兩個 goroutine 修改 WaitGroup 的相同實例,並向主執行緒正確發出完成訊號。

這是經過更正的程式碼修訂版:

package main<p><br>import (</p><p></p>)<pre class="brush:php;toolbar:false">"fmt"
"sync"
登入後複製
import (

)

import (
for i := 0; i < 5; i++ {
    c <- i
}
wg.Done()
登入後複製
登入後複製

)

import (

for i := 0; i < 5; i++ {
    result, ok := <-c
    fmt.Println(result, ok)
}
wg.Done()
登入後複製
登入後複製

)

func push(c chan int, wg *sync.WaitGroup) {

var wg sync.WaitGroup
wg.Add(2)
c := make(chan int)

go push(c, &wg) // Pass the WaitGroup by reference using the ampersand
go pull(c, &wg) // Pass the WaitGroup by reference using the ampersand

wg.Wait()
登入後複製

}

func pull(c chan int, wg *sync.WaitGroup) {

}func main() {}透過引用傳遞WaitGroup,我們確保主執行緒能夠正確判斷兩個goroutines何時完成任務,以避免死鎖。

以上是為什麼在 Go 中按值傳遞 WaitGroup 會導致死鎖,如何解決?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板