英文:
Why is deadlock posssible here?
问题
我正在学习关于Go语言中死锁及其出现的情况。我正在查看这段代码。我知道这里可能会出现死锁,但我找不到具体原因。有人可以解释一下吗?
package main
import "fmt"
func reuters(ch chan string) {
ch <- "REUTERS"
}
func bloomberg(ch chan string) {
ch <- "BLOOMBERG"
}
func newsReader(reutersCh chan string, bloombergCh chan string) {
ch := make(chan string, 5)
go func() {
ch <- (<-reutersCh)
}()
go func() {
ch <- (<-bloombergCh)
}()
x := <-ch
fmt.Printf("got news from %s \n", x)
}
func main() {
reutersCh := make(chan string)
bloombergCh := make(chan string)
go reuters(reutersCh)
go bloomberg(bloombergCh)
newsReader(reutersCh, bloombergCh)
newsReader(reutersCh, bloombergCh)
}
这段代码中可能会出现死锁的原因是:在newsReader
函数中,有两个goroutine分别从reutersCh
和bloombergCh
通道中接收数据,并将数据发送到ch
通道中。然后,在主函数中,我们调用了两次newsReader
函数,每次都使用相同的reutersCh
和bloombergCh
通道。由于ch
通道的缓冲区大小为5,而我们只从中接收了一个数据,所以第二次调用newsReader
函数时,将会发生死锁。因为第二次调用时,ch
通道已经被第一次调用中的goroutine占满,无法再接收新的数据。
为了解决这个问题,你可以将ch
通道的缓冲区大小增加到足够大,以容纳所有的数据,或者在每次调用newsReader
函数时,使用新的通道来避免死锁。
英文:
I am currently learning about deadlocks in Go and when they can appear. I am viewing this code. I know a deadlock is possible here, but I cannot find it. Can someone please explain it to me?
package main
import "fmt"
func reuters(ch chan string) {
ch <- "REUTERS"
}
func bloomberg(ch chan string) {
ch <- "BLOOMBERG"
}
func newsReader(reutersCh chan string, bloombergCh chan string) {
ch := make(chan string, 5)
go func() {
ch <- (<-reutersCh)
}()
go func() {
ch <- (<-bloombergCh)
}()
x := <-ch
fmt.Printf("got news from %s \n", x)
}
func main() {
reutersCh := make(chan string)
bloombergCh := make(chan string)
go reuters(reutersCh)
go bloomberg(bloombergCh)
newsReader(reutersCh, bloombergCh)
newsReader(reutersCh, bloombergCh)
}
答案1
得分: 2
当你想从一个空通道中读取时,该通道会阻塞。在运行以下代码之后:
go reuters(reutersCh)
go bloomberg(bloombergCh)
reutersCh
通道中会有一个项目,bloombergCh
通道中也会有一个项目。当你运行
newsReader(reutersCh, bloombergCh)
你启动了两个从两个通道中读取的例程。很有可能,在第二次运行
newsReader(reutersCh, bloombergCh)
之前,这两个例程就已经完成了。在这种情况下,reutersCh
和 bloombergCh
是空的,所以你无法从它们中读取。当你无法从这些通道中读取时,你也无法向 newsReader
函数中的本地通道 ch
写入。当你无法向通道 ch
写入时,你也无法从通道中读取,因此它会阻塞。
总之,你在 reutersCh
和 bloombergCh
中写入一次,并尝试从它们中读取两次。两个例程肯定会阻塞,当第二次调用 newsReader
的两个例程阻塞时(这是非常可能的),你的程序将完全阻塞。
英文:
When you want to read from an empty channel, the channel blocks. After running:
go reuters(reutersCh)
go bloomberg(bloombergCh)
there will be one item in reutersCh
and one item in bloombergCh
. When you run
newsReader(reutersCh, bloombergCh)
you start two routines that read from both channels. It is very likely, that they finish before
newsReader(reutersCh, bloombergCh)
runs a second time. In this case, reutersCh
and bloombergCh
are empty, so der is no way you can read from them. When you can't read from these channels, you also can't write to the local channel ch
in the newsReader
function. When you can't write to the channel ch
you can't read from the channel and therefore it blocks.
In conclusion, you write in reutersCh
and bloombergCh
once and try to read from them twice. Two routines will block for sure and when the two routines from the second call of newsReader
block (which is very likely), your program will block completely.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论