首頁 > 後端開發 > Golang > 在 Go 中使用 WaitGroups 和緩衝通道時如何防止死鎖?

在 Go 中使用 WaitGroups 和緩衝通道時如何防止死鎖?

Linda Hamilton
發布: 2024-10-26 18:10:02
原創
407 人瀏覽過

How can I prevent deadlock when using WaitGroups and buffered channels in Go?

Go 中的死鎖:WaitGroup 和緩衝通道

在Go 中,當並發goroutine 無限期地等待彼此完成時,就會發生死鎖。死鎖的一個常見原因涉及使用 WaitGroups 和緩衝通道。

死鎖範例

考慮以下程式碼:

<code class="go">package main

import "fmt"
import "sync"

func main() {
    ch := make(chan []int, 4)
    var m []int

    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            ch <- m // Sending to a full channel
            return
        }()
    }
    wg.Wait()

    for c := range ch {
        fmt.Printf("c is %v", c)
    }
}</code>
登入後複製

此程式碼打算將5 個空切片傳送到容量為4 的緩衝通道,然後在所有goroutine 完成後從通道中讀取。但是,該程式碼會導致死鎖錯誤。

死鎖的原因

死鎖是由於兩個問題引起的:

  1. 通道緩衝區不足:通道容量為4,對於5 個嘗試發送資料的goroutine 來說太小了。當通道變滿時,後續等待發送資料的 goroutine(第 15 行)將無限期地阻塞。
  2. 阻塞通道迭代: 迭代通道的循環(第 22-24 行)會阻塞無限期地,因為它等待更多元素到達通道。由於所有 goroutine 都已完成發送數據,並且預計不再有數據,因此如果沒有相應的 goroutine 從通道讀取數據,本次迭代將永遠不會完成。

解決方案

要解決死鎖,請進行以下修改之一:

解決方案1:

將通道容量增加到5(或更多)並在發送完所有資料後將其關閉:

<code class="go">ch := make(chan []int, 5)
...
wg.Wait()
close(ch)</code>
登入後複製

解決方案2:

啟動一個單獨的goroutine從通道讀取數據,並在接收到所有數據後通知主goroutine:

<code class="go">func main() {
    ch := make(chan []int, 4)
    var m []int

    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            ch <- m
            wg.Done()
        }()
    }
    go func() {
        for c := range ch {
            fmt.Printf("c is %v\n", c)
            wg.Done()
        }
    }()
    wg.Wait()
}</code>
登入後複製

以上是在 Go 中使用 WaitGroups 和緩衝通道時如何防止死鎖?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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