猿问

golang 通道在接收值之前死锁

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

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


慕妹3242003
浏览 145回答 3
3回答

撒科打诨

默认情况下,Go 通道是无缓冲的。这意味着在接收方读取通道之前,它不能在通道上发送。这实际上是 Go 的首选模式。在大多数情况下,它比缓冲通道更有效。这对您的第一个代码意味着 goroutine 在完成对通道 a 的写入之前无法继续写入通道 b。在主 goroutine 读取 a 之前,它不能这样做。

蝴蝶刀刀

默认情况下,通道发送和接收会等待发送例程和接收例程都准备就绪。通过以下示例可以明显看出这种阻塞:func main() {     ch := make(chan int)     ch <- 1     fmt.Println(<-ch) }这段代码会导致死锁,因为唯一的 goroutine(主协程)卡在ch <- 1,等待另一个 goroutine 接收。它几乎不知道我们期望它成为下一行的接收者。这解释了为什么您的第一个示例不起作用,因为另一个 goroutineb在其发送操作a完成之前不会发送。a但是主例程在收到之前不会收到b!所以两者都永远等待着。

料青山看我应如是

如果您按照顺序执行的方式重写代码,那么发生的事情就会变得更加清晰。原始代码:func main() {&nbsp; &nbsp; a := make(chan bool)&nbsp; &nbsp; b := make(chan int64)&nbsp; &nbsp; go func(a chan bool, b chan int64) {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Here1")&nbsp; &nbsp; &nbsp; &nbsp; a <- true&nbsp; &nbsp; &nbsp; &nbsp; b <- 12&nbsp; &nbsp; } (a,b)&nbsp; &nbsp; fmt.Println("Here2")&nbsp; &nbsp; fmt.Println(fmt.Sprintf("%d", <-b))&nbsp; &nbsp; fmt.Println(fmt.Sprintf("%v", <-a))}相同代码顺序执行的紧密表示:&nbsp; &nbsp; a := make(chan bool)&nbsp; &nbsp; b := make(chan int64)&nbsp; &nbsp; fmt.Println("Here2") // Prints&nbsp; &nbsp; // Pass control to new goroutine&nbsp; &nbsp; fmt.Println("Here1")&nbsp; &nbsp; a <- true&nbsp; &nbsp; &nbsp;// Write to channel a and block goroutine here and pass control to main&nbsp; &nbsp; fmt.Println(fmt.Sprintf("%d", <-b)) // Tries to read from b but nothing has been written to it so blocks. At this point all your goroutines are blocked hence the deadlock.&nbsp; &nbsp; fmt.Println(fmt.Sprintf("%v", <-a)) // doesn't even reach here.&nbsp; &nbsp; b <- 12}
随时随地看视频慕课网APP

相关分类

Go
我要回答