这是一个关于无缓冲 channel 的简单示例代码:
ch01 := make(chan string)
go func() {
fmt.Println("We are in the sub goroutine")
fmt.Println(<-ch01)
}()
fmt.Println("We are in the main goroutine")
ch01 <- "Hello"
我得到的结果:
We are in the main goroutine
We are in the sub goroutine
Hello
去 Playground : https://play.golang.org/p/rFWQbwXRzGw
据我了解,发送操作阻塞了主协程,直到子协程在 channel ch01
上执行了接收操作。 .然后程序退出。
像这样在发送操作之后放置子 goroutine 之后:
fmt.Println("We are in the main goroutine")
ch01 <- "Hello"
go func() {
fmt.Println("We are in the sub goroutine")
fmt.Println(<-ch01)
}()
发生死锁:
We are in the main goroutine
fatal error: all goroutines are asleep - deadlock!
去 Playground https://play.golang.org/p/DmRUiBG4UmZ
这次发生了什么?这是否意味着在 ch01 <- "Hello"
之后主goroutine立即被阻塞,让sub goroutine没有机会运行?如果是真的,我应该如何理解第一个代码示例的结果?(首先在主协程中,然后在子协程中)。
最佳答案
无缓冲 channel 在发送时阻塞,直到接收方准备好读取。在您的第一个示例中,首先设置了一个阅读器,因此当发送发生时,它可以立即发送。
在你的第二个例子中,发送发生在接收者准备好之前,所以发送阻塞和程序死锁。
您可以通过创建缓冲 channel 来修复第二个示例,但是您有可能永远看不到 goroutine 的输出,因为程序可能会在刷新输出缓冲区之前退出(主 goroutine)。 goroutine 在被调度之前甚至可能不会作为主导出运行。
关于go - Go 中的无缓冲 channel ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49958153/