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

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

Linda Hamilton
Linda Hamilton原創
2024-10-28 04:16:30665瀏覽

How Can Deadlock Occur When Using WaitGroups and Buffered Channels in Go?

使用WaitGroup 進行Go 並發中的死鎖檢測

在Go 中,通常使用通道和等待組來編排。但是,了解可能導致死鎖的潛在陷阱非常重要。

問題描述

考慮以下嘗試使用緩衝通道和等待組的代碼:

<code class="go">package main

import (
    "fmt"
    "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 // Send to channel
            return
        }()
    }
    wg.Wait() // Wait for all goroutines to complete

    for c := range ch {
        fmt.Printf("c is %v", c) // Iterate over channel
    }
}</code>

儘管期望通道在達到其容量後自動關閉,但此程式碼意外地導致了死鎖錯誤。

有兩個導致死鎖的關鍵問題:

  1. 通道容量不足:通道緩衝區的容量為4,而有5個goroutines試圖寫入它。這會導致等待寫入的 goroutine 被阻塞,因為通道已滿。
  2. 未關閉通道上的範圍: c := range ch 的循環繼續偵聽來自無限期地等待通道關閉。然而,由於沒有 goroutines 繼續寫入通道,所以它永遠不會關閉。

要解決死鎖,有兩種解決方案:

解決方案1: 擴充通道容量並明確關閉

<code class="go">ch := make(chan []int, 5) // Increase channel capacity
...
wg.Wait()
close(ch) // Close the channel to stop range loop</code>

這確保通道中有足夠的空間並明確關閉它,從而允許範圍循環終止。

解決方案2: 在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() // Signal completion within goroutine
            return
        }()
    }
    go func() {
        for c := range ch {
            fmt.Printf("c is %v\n", c)
            wg.Done() //Decrement count for each iteration
        }
    }()
    wg.Wait()
}</code>

在此解決方案中,每個Goroutine 通過在Goroutine 本身內部呼叫wg.Done() 來發出完成訊號。每次迭代的 waitgroup 也會在範圍循環內遞減,確保 wg.Wait() 最終完成並且程式終止。

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

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn