-2

所以我一直在尝试使用 WaitGroup 并行运行多个 goroutine。无论我尝试什么,我总是以“致命错误:所有 goroutine 都处于睡眠状态 - 死锁!”而告终。

这就是我的代码现在的样子:

package main

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

func main() {
    ch := make(chan time.Duration)

    var wg sync.WaitGroup

    for _, v := range []time.Duration{5, 1} {
        wg.Add(1)

        go func() {
            defer wg.Done()
            wait(v, ch)
        }()
    }

    wg.Wait()
}

func wait(seconds time.Duration, c chan time.Duration) {
    time.Sleep(seconds * time.Second)
    c <- seconds
}

然而,这会导致死锁,我不知道为什么。

我一直在尝试使用以下代码读取 WaitGroup 之后的值:

    close(ch)

    for v := range ch {
        fmt.Println(v)
    }

然而,它似乎甚至不会到达这部分。

谢谢!

4

2 回答 2

1

所有工作人员完成后,您需要关闭工作人员频道。您将立即从主 goroutine 关闭它。

所以这样做:

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

此外,您的等待功能已经需要 a time.Duration,所以它应该是实时的,而不是乘以time.Second。如果要以秒为单位传递,请考虑更改输入类型int以避免混淆。

于 2021-06-24T19:58:27.990 回答
1

代码有两个问题:

  1. 只有在所有 go-routines 完成后,您才必须关闭通道
  2. v 的值在迭代过程中丢失

在 go 中,for 循环将重用 v,因此所有 go-routines 在等待调用时将具有相同的值。

package main

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

func main() {
    ch := make(chan time.Duration)

    var wg sync.WaitGroup

    for _, v := range []time.Duration{5, 1} {
        wg.Add(1)
        v := v // <- this

        go func() {
            defer wg.Done()
            wait(v, ch)
        }()
    }

    go func() { // Close the channel only after go-routines finish
        wg.Wait()
        close(ch)
    }()

    for v := range ch { // Will loop until channel is closed
        fmt.Println(v)
    }
}

func wait(seconds time.Duration, c chan time.Duration) {
    time.Sleep(seconds * time.Second)
    c <- seconds
}
于 2021-06-24T20:01:05.523 回答