英文:
Closing channels in Go
问题
我正在学习Go语言中的通道工作原理,并在关闭通道方面遇到了问题。这是来自《Go之旅》的一个修改过的示例,它生成n-1个斐波那契数,并通过通道发送它们,留下通道容量的最后一个"元素"未使用。
问题是,当我不关闭通道时,我会得到以下错误信息:
fatal error: all goroutines are asleep - deadlock!
造成死锁的原因是什么?为什么在不关闭通道的情况下,我不能在其容量边界内接收通道的值?
英文:
I am learning how channels work in Go and have stumbled upon a problem with closing the channels. This is a modified example from A Tour of Go, which generates n-1 fibonacci numbers and sends them through the channels, leaving the last "element" of the channel capacity unused.
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n-1; i++ {
c <- x
x, y = y, x+y
}
// close(c) // It's commented out on purpose
}
func main() {
n := 10
c := make(chan int, n)
go fibonacci(n, c)
for i := 0; i < n; i++ {
_, ok := <-c
fmt.Println(ok)
}
}
The problem is that I get:
> fatal error: all goroutines are asleep - deadlock!
when I do not close the channel. What exactly is causing the deadlock? Why can't I receive from the channel in its capacity boundaries when I don't close it?
答案1
得分: 5
你正在将n个值写入通道(从0到n-1),但尝试从通道中读取n+1个值(从0到n)。如果没有显式关闭通道,main
函数将永远等待最后一个值。
是什么导致了死锁?
经过n次迭代后,运行fibonacci
函数的goroutine将退出。在此goroutine退出后,程序中唯一剩下的goroutine是main
goroutine,而此goroutine正在等待某些数据被写入c
通道中,由于没有其他可能写入数据到该通道的goroutine,它将永远等待。这正是错误消息试图告诉你的:“所有goroutine(这里只有一个)都处于休眠状态”。
main
函数中的_, ok := <- c
调用只有在c
通道关闭时才会停止阻塞(由于从通道读取是阻塞的,这需要从另一个goroutine中完成)。当通道关闭时,main
函数将从通道中读取剩余的数据(当它是缓冲通道时)。
英文:
You're writing n values into the channel (from 0 to n-1), but are trying to read n+1 values from the channel (from 0 to n). Without explicitly closing the channel, the main
function will wait forever for this last value.
>What exactly is causing the deadlock?
After n iterations, the goroutine running the fibonacci
function will exit. After this goroutine has exited, the only remaining goroutine in your program is the main
goroutine, and this goroutine is waiting for some data to be written to the c
channel -- and since there is no other goroutine left that might ever write data into this channel, it will wait forever. This is exactly what the error message is trying to tell you: "all goroutines ("all" is just "one", here) are asleep".
The _, ok := <- c
call in the main
function will only stop blocking as soon as the c
channel is closed (as reading from a channel is blocking, this needs to be done from another goroutine). When the channel is closed, the main
function will read remaining data from the channel (when it's a buffered channel)
答案2
得分: 0
在主函数中的for循环期望在通道中进行n次通信,但在fibonacci函数中你只产生了n-1次通信。
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n; i++ { //这里
c <- x
x, y = y, x+y
}
// close(c) //这行是有意注释掉的
}
应该这样修改:
http://play.golang.org/p/zdRuy14f9x
英文:
For loop in main expect n communication in channel, but you produce only n-1 in func fibonacci
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n; i++ { //here
c <- x
x, y = y, x+y
}
// close(c) // It's commented out on purpose
}
should work
http://play.golang.org/p/zdRuy14f9x
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论