首頁 > 後端開發 > Golang > 使用sync.WaitGroup時如何修復Go頻道中的死鎖錯誤?

使用sync.WaitGroup時如何修復Go頻道中的死鎖錯誤?

Patricia Arquette
發布: 2024-10-29 02:36:02
原創
469 人瀏覽過

How to Fix Deadlock Errors in Go Channels When Using sync.WaitGroup?

了解 Go Channel 中的死鎖錯誤

在本文中,我們將分析「死鎖」背後的原因!下列程式碼片段涉及Go 通道的死鎖情況所造成的錯誤:

package main

import (
    "fmt"
    "sync"
)

func push(c chan int, wg sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        c <- i
    }
    wg.Done()
}

func pull(c chan int, wg sync.WaitGroup) {
    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()
}
登入後複製

執行此程式碼時,我們遇到以下錯誤:

throw: all goroutines are asleep - deadlock!
登入後複製

理解死鎖

發生死鎖是因為結構(例如此程式碼中的sync.WaitGroup)是按值傳遞而不是按引用傳遞。這意味著當我們將 WaitGroup 傳遞給我們的函數(推和拉)時,我們實際上傳遞的是 WaitGroup 的副本而不是原始物件。

因此,每個函數都在自己的副本上工作WaitGroup 的副本,當它們呼叫 wg.Done() 時,它們會遞減自己的副本。這不會更新我們的主協程正在等待的原始 WaitGroup,從而導致死鎖。

修復死鎖

要解決這個問題,我們需要傳遞指標到 WaitGroup 而不是值。這將確保推送和拉取函數都在 WaitGroup 的同一個實例上運作,並且它們對 wg.Done() 的呼叫將影響原始物件。

這是程式碼的更正版本:

package main

import (
    "fmt"
    "sync"
)

func push(c chan int, wg *sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        c <- i
    }
    wg.Done()
}

func pull(c chan int, wg *sync.WaitGroup) {
    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()
}
登入後複製

透過進行此更改,我們現在將指向WaitGroup 的指標傳遞給我們的函數,確保它們都在同一物件上工作並正確更新其狀態。這消除了死鎖情況,讓我們的程式能夠無錯誤地運作。

以上是使用sync.WaitGroup時如何修復Go頻道中的死鎖錯誤?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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