首页 >后端开发 >Golang >为什么我的 Go WaitGroup 会导致'所有 Goroutine 都处于睡眠状态 - 死锁!”错误?

为什么我的 Go WaitGroup 会导致'所有 Goroutine 都处于睡眠状态 - 死锁!”错误?

Barbara Streisand
Barbara Streisand原创
2024-12-25 19:14:17764浏览

Why Does My Go WaitGroup Cause a

WaitGroup 死锁:理解“所有 Goroutine 都处于睡眠状态 - 死锁!”

当尝试使用 WaitGroup 协调 Goroutines 时,可能会遇到错误“致命错误:所有 goroutine 都在睡觉 - 死锁!”。当负责递减 WaitGroup 计数器的 goroutine 无意中结束睡眠时,就会发生这种情况。

问题:

以下 Go 代码说明了如何出现此错误:

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            fmt.Println("Hello", i)
        }()
    }
    wg.Wait()
}

执行后,此代码应为每个 goroutine 打印“Hello”。然而,程序却以可怕的“死锁”错误退出。

原因:

问题在于 WaitGroup 传递给 goroutine 的方式。当值传递给匿名函数时,Go 会生成该值的副本。因此,每个 goroutine 都在 WaitGroup 的单独副本上运行,其中没有一个副本的计数器递减,从而导致 goroutine 永久睡眠。

解决方案:

要解决死锁,必须传递指向 WaitGroup 的指针而不是 WaitGroup 本身。因此,所有 goroutine 将引用相同的 WaitGroup,使它们能够正确地递减其计数器:

package main

import (
    "fmt"
    "sync"
)

func main() {
    wg := &sync.WaitGroup{}
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            fmt.Println("Hello", i)
        }()
    }
    wg.Wait()
}

通过传递指针,goroutines 共享相同的 WaitGroup 对象并可以成功协调它们的执行。此版本的代码将为每个 goroutine 正确打印“Hello”,而不会触发死锁。

以上是为什么我的 Go WaitGroup 会导致'所有 Goroutine 都处于睡眠状态 - 死锁!”错误?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn