首頁 >後端開發 >Golang >當所有 Goroutine 都處於睡眠狀態時,如何解決 Go 中的死鎖?

當所有 Goroutine 都處於睡眠狀態時,如何解決 Go 中的死鎖?

Susan Sarandon
Susan Sarandon原創
2024-12-24 10:43:171034瀏覽

How to Resolve Deadlocks in Go When All Goroutines Are Asleep?

Go 中的死鎖:「所有Goroutine 都處於睡眠狀態」

在使用Goroutine 時,有效管理通道操作以避免死鎖至關重要。當所有 goroutine 無限期地阻塞時,就會發生這種情況,從而導致死鎖情況。

理解程式碼

讓我們檢查一下提供的程式碼:

package main

import (
    "fmt"
    "sync"
    "time"
)

type Item struct {
    name string
}

type Truck struct {
    Cargo []Item
    name  string
}

func UnloadTrucks(c chan Truck) {
    for t := range c {
        fmt.Printf("%s has %d items in cargo: %s\n", t.name, len(t.Cargo), t.Cargo[0].name)
    }
}

func main() {
    trucks := make([]Truck, 2)
    ch := make(chan Truck)

    for i, _ := range trucks {
        trucks[i].name = fmt.Sprintf("Truck %d", i+1)
        fmt.Printf("Building %s\n", trucks[i].name)
    }

    for t := range trucks {
        go func(tr Truck) {
            itm := Item{}
            itm.name = "Groceries"

            fmt.Printf("Loading %s\n", tr.name)
            tr.Cargo = append(tr.Cargo, itm)
            ch <- tr
        }(trucks[t])
    }

    time.Sleep(50 * time.Millisecond)
    fmt.Println("Unloading Trucks")
    UnloadTrucks(ch)

    fmt.Println("Done")
}

此程式碼建立一個Truck 類型的通道ch 並啟動兩個goroutine 來模擬用雜貨裝載卡車並將它們發送到頻道。然後它調用 UnloadTrucks 檢索並列印卡車的內容。

死鎖原因

問題在於缺乏關閉 ch 通道的機制。當所有 goroutine 都將卡車發送到通道時,UnloadTrucks 中沒有終止循環的訊號。這意味著 ch 會一直監聽永遠不會到達的值,導致死鎖。

解決方案

要解決死鎖,我們需要在以下情況下明確關閉 ch 通道:載入 goroutine 已完成。我們可以使用sync.WaitGroup來計算正在運行的goroutines,並在所有goroutines完成後關閉通道:

var wg sync.WaitGroup

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

此修改確保一旦所有goroutines完成裝載卡車,UnloadTrucks將終止。 Wait 函數會阻塞,直到 WaitGroup 計數器達到零,這表示所有 goroutine 都已完成其工作。關閉通道會向 UnloadTrucks 發出不再接收卡車的信號,使其優雅地退出循環。

以上是當所有 Goroutine 都處於睡眠狀態時,如何解決 Go 中的死鎖?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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