Golang通道在接收值之前死锁

时间:2019-01-24 01:17:16

标签: go

我不明白为什么这个方法https://play.golang.org/p/_ALPii0pXV6不起作用,但是这个https://play.golang.org/p/vCOjAr-o54e有效。

据我所知,goroutine异步发送给a的值true和12到b的值。在主函数中,a被阻塞,直到它接收到一个值。为什么当我重新排列它以使b在a之前被阻塞时会导致死锁?

2 个答案:

答案 0 :(得分:3)

默认情况下,转到通道未缓冲。这意味着它无法在频道上发送,直到接收者正在读取频道为止。这实际上是Go首选模式。在大多数情况下,它比缓冲通道更有效。

这对于您的第一个代码意味着goroutine在完成对通道a的写入之前无法继续写入通道b。在主goroutine读取a之前,它无法执行此操作。

答案 1 :(得分:3)

以示例explains为例,默认情况下,通道发送和接收要等到发送例程和接收例程都准备好为止。 the following example使这种阻塞变得显而易见:

func main() {
    ch := make(chan int)
    ch <- 1
    fmt.Println(<-ch)
}

此代码将导致死锁,因为唯一的goroutine(主要的goroutine)停留在ch <- 1上,等待另一个goroutine接收。它几乎不知道我们期望它成为下一行的接收者。

这说明了您的第一个示例为何不起作用的原因,因为另一个goroutine在b上的发送操作完成之前不会在a上发送。但是,直到在a上收到主例程之后,它才能在b上接收!因此,两者都被卡在永远的等待中。

要详细了解这种操作(称为同步操作),请查看this explanation