我不明白为什么这个方法https://play.golang.org/p/_ALPii0pXV6不起作用,但是这个https://play.golang.org/p/vCOjAr-o54e有效。
据我所知,goroutine异步发送给a的值true和12到b的值。在主函数中,a被阻塞,直到它接收到一个值。为什么当我重新排列它以使b在a之前被阻塞时会导致死锁?
答案 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。