首頁 > 後端開發 > Golang > 在 Go 中使用帶有外部函數的sync.WaitGroup時如何避免死鎖?

在 Go 中使用帶有外部函數的sync.WaitGroup時如何避免死鎖?

Mary-Kate Olsen
發布: 2024-11-05 22:03:02
原創
964 人瀏覽過

How to Avoid Deadlocks When Using sync.WaitGroup with External Functions in Go?

將sync.WaitGroup與外部函數結合使用的最佳實踐

在處理Go中的並發時,有效利用至關重要。本文解決了將等待群組作為參數傳遞給外部函數時出現的常見問題。

問題:

考慮以下程式碼:

<code class="go">package main

import (
    "fmt"
    "sync"
)

func main() {
    ch := make(chan int)
    var wg sync.WaitGroup
    wg.Add(2)
    go Print(ch, wg) //
    go func(){

        for i := 1; i <= 11; i++ {
            ch <- i
        }

        close(ch)
        defer wg.Done()


    }()

    wg.Wait() //deadlock here
}

// Print prints all numbers sent on the channel.
// The function returns when the channel is closed.
func Print(ch <-chan int, wg sync.WaitGroup) {
    for n := range ch { // reads from channel until it's closed
        fmt.Println(n)
    }
    defer wg.Done()
}</code>
登入後複製

這段程式碼中,在指定行發生死鎖,導致程式只印從1到10,而不是到達11。此錯誤源自於將sync.WaitGroup的副本傳遞給Print方法,這阻礙了對其 Done 方法的預期呼叫。

解決方案1:

要解決此問題,請將指標傳遞給等待群組:

<code class="go">package main

import (
    "fmt"
    "sync"
)

func main() {    
    ch := make(chan int)

    var wg sync.WaitGroup
    wg.Add(2)    

    go Print(ch, &wg)

    go func() {  
        for i := 1; i <= 11; i++ {
            ch <- i
        }
        close(ch)
        defer wg.Done()
    }()          

    wg.Wait() //deadlock here
}                

func Print(ch <-chan int, wg *sync.WaitGroup) {
    for n := range ch { // reads from channel until it's closed
        fmt.Println(n)
    }            
    defer wg.Done()
}</code>
登入後複製

傳遞wg 的位址可以確保Print 方法呼叫main 函數中等待的等待群組上的Done 方法。

解決方案2:簡化的Print 方法

或者,可以透過刪除WaitGroup 參數來簡化Print 方法,因為它不需要了解任何等待操作:

<code class="go">package main

import (
    "fmt"
)

func main() {    
    ch := make(chan int)
    go func() {  
        for i := 1; i <= 11; i++ {
            ch <- i
        }
        close(ch)
    }()          

    for n := range ch { // reads from channel until it's closed
        fmt.Println(n)
    }            
}                </code>
登入後複製

在這種情況下,主goroutine 直接接收通道並列印它的值不涉及等待群組。這種方法保留了所需的功能,並消除了 Print 方法中對 WaitGroup 管理的需求。

結論:

當將sync.WaitGroup 作為參數傳遞給外部函數時,確保函數接收到正在等待的等待組的正確引用至關重要。重構函數以直接處理等待群組或傳遞指標到等待群組可以有效防止死鎖錯誤並確保正確的並發控制。

以上是在 Go 中使用帶有外部函數的sync.WaitGroup時如何避免死鎖?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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