在通道上使用例程时出现死锁问题

时间:2018-07-16 08:14:58

标签: go concurrency channel goroutine

在通道上使用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!

我不明白为什么会发生此问题。请帮助我理解

1 个答案:

答案 0 :(得分:3)

在您的示例中,您有2个goroutine:运行main()函数的主goroutine,另一个在其中运行的goroutine。主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