首页 > 后端开发 > Golang > 当所有 Goroutine 都处于睡眠状态时,如何解决 Go 中的死锁?

当所有 Goroutine 都处于睡眠状态时,如何解决 Go 中的死锁?

Susan Sarandon
发布: 2024-12-24 10:43:17
原创
1071 人浏览过

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中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板