将例程与通道一起使用时出现死锁问题

Deadlock issue when using routine with channel

我在将 Go 例程与通道一起使用时遇到问题。代码如下所示:

func main() {
    c := make(chan int)
    var wg sync.WaitGroup

    wg.Add(1)
    go func (c chan int, x int) {
        c <- x
        fmt.Println(x)
        close(c)

        defer wg.Done()
    }(c,10)

    wg.Wait()
}

当运行代码我得到这个错误:

fatal error: all goroutines are asleep - deadlock!

我不明白为什么会出现这个问题。请帮助我理解

您的示例中有 2 个 goroutine:主 goroutine 运行 main() 函数,另一个在其中启动。主 goroutine 等待另一个 goroutine 完成(调用 wg.Done()),其他 goroutine 阻塞在它试图在通道 c 上发送值的行中。由于没有人从那个通道接收数据,并且因为那个通道是无缓冲的,所以这个 goroutine 永远不会前进,所以你所有的 2 个 goroutine 都会永远阻塞。

注意defer wg.Done()应该是goroutine中的第一条语句。如果是最后一个,defer 没有任何区别。

如果通道的缓冲区至少为 1,则发送操作可以继续:

c := make(chan int, 1)

输出将是(在 Go Playground 上尝试):

10

如果我们让通道不带缓冲,则必须有另一个 goroutine 从通道接收,例如:

wg.Add(1)
go func() {
    defer wg.Done()
    x := <-c
    fmt.Println("Received:", x)
}()

然后输出将是(在 Go Playground 上尝试):

10
Received: 10