首頁 > 後端開發 > Golang > 主體

當生產者壽命較短時,如何避免 Go Goroutine 死鎖?

Linda Hamilton
發布: 2024-10-25 07:09:02
原創
792 人瀏覽過

How to Avoid Deadlock in Go Goroutines When Producers Are Short-Lived?

解決Go Goroutine 中的死鎖

在並發程式設計中,當多個Goroutine 無限期地等待彼此完成操作時,就會發生死鎖,從而有效地停止進程程序。本文解決了Go 並發中遇到的特定死鎖,如原始問題中所述:

<code class="go">package main

import (
    "fmt"
    "time"
)

func producer(ch chan int, d time.Duration, num int) {
    for i := 0; i < num; i++ {
        ch <- i
        time.Sleep(d)
    }
}

func main() {
    ch := make(chan int)
    go producer(ch, 100*time.Millisecond, 2)
    go producer(ch, 200*time.Millisecond, 5)
    for {
        fmt.Println(<-ch)
    }
    close(ch)
}</code>
登入後複製

此程式碼由於以下因素觸發死鎖錯誤:

  • 生產者向通道發送值的過程是短暫的,最終會停止產生資料。
  • 主函數中的無限 for 迴圈不斷從通道接收值,沒有終止條件。
  • 無限循環後通道關閉,導致沒有更多的值可用於接收。

解決方案:協調終止

為了避免死鎖,生產者必須協調以發出完成信號,並且通道必須由最後一個生產者關閉。這是使用sync.WaitGroup進行協調的有效解決方案:

<code class="go">func producer(ch chan int, d time.Duration, num int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < num; i++ {
        ch <- i
        time.Sleep(d)
    }
}

func main() {
    wg := &sync.WaitGroup{}
    ch := make(chan int)

    wg.Add(1)
    go producer(ch, 100*time.Millisecond, 2, wg)
    wg.Add(1)
    go producer(ch, 200*time.Millisecond, 5, wg)

    go func() {
        wg.Wait()
        close(ch)
    }()

    for v := range ch {
        fmt.Println(v)
    }
}</code>
登入後複製

在此解決方案中:

  • 我們為每個生產者增加WaitGroup。
  • 每個生產者透過 defer 語句在完成後遞減 WaitGroup。
  • goroutine 等待 WaitGroup 達到零(意味著所有生產者都完成)並關閉通道。
  • 主循環使用 for range構造以在關閉之前迭代通道上發送的值。

以上是當生產者壽命較短時,如何避免 Go Goroutine 死鎖?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!