为什么我的代码在从通道读取时死锁(然后崩溃),我希望它在通道完全读取后在读取时阻塞,但不会崩溃。我知道这是一种死锁状态,因为没有人在通道上写入和读取数据块。
如何更改代码以读取所有频道内容,然后从main退出,而不是crash。
Go游乐场:https://play.golang.org/p/rjXZZOx1FFZ
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
news := make(chan int, 10)
wg.Add(1)
go foo(&wg, news)
wg.Wait()
for {
fmt.Printf("reading: %v\n", <-news)
//crashes here after printing 0-9
}
}
func foo(wg *sync.WaitGroup, news chan int) {
for i:=0; i<10;i++ {
fmt.Printf("Writing\n")
news <- i
}
(*wg).Done()
}发布于 2018-08-31 07:28:53
程序死锁,因为通道上的主块接收,并且没有其他goroutines将发送到该通道。
使用这种方法读取所有通道内容,然后从main退出:main读取通道直到关闭;foo写入所有值并关闭通道。
func main() {
news := make(chan int, 10)
go foo(news)
// range breaks when the channel is closed
for v := range news {
fmt.Printf("reading: %v\n", v)
}
}
func foo(news chan int) {
for i := 0; i < 10; i++ {
fmt.Printf("Writing\n")
news <- i
}
// close channel to indicate that no more values will be sent.
close(news)
}发布于 2018-08-31 07:41:16
要解释为什么会发生这种情况,你会从死机中得到的错误消息告诉你它的要点:
fatal error: all goroutines are asleep - deadlock!你不能让你所有的goroutine等待其他goroutine去做某件事。在这种情况下,当运行foo的goroutine完成,并且运行main的goroutine已经接收到发送到news通道的所有消息(0到9)时,您的程序只剩下一个goroutine等待在一个通道上接收消息,这个通道再也不会有消息发送给它了,因为没有其他goroutine可以这样做。
发布于 2018-08-31 07:55:03
代码因死锁而崩溃。
fatal error: all goroutines are asleep - deadlock!
您在原始代码中遇到了一些有趣的问题。
如果您关闭了foo goroutine中的新闻频道,而不是死锁,那么您将永远在main中运行无限循环。
2简单的代码更改应该会使这一点变得更清楚,并将导致它在处理news项后退出。
https://play.golang.org/p/qSU7sV7Wrov
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
news := make(chan int, 10)
wg.Add(1)
go foo(&wg, news)
wg.Wait()
for n := range news {
fmt.Printf("reading: %v\n", n)
}
fmt.Println("We're out of news!")
}
func foo(wg *sync.WaitGroup, news chan int) {
for i := 0; i < 10; i++ {
fmt.Printf("Writing\n")
news <- i
}
close(news)
wg.Done()
}当然,您可以不使用WaitGroups重写它,而只是像其他人指出的那样使用通道,这可能是一个更优雅的解决方案。
https://stackoverflow.com/questions/52106572
复制相似问题