我想编写三个同时发送整数的并发go例程。现在,我的代码已正确编译,但是在第一次执行后,出现错误“所有goroutine都处于睡眠状态- 死锁!”。我试图找到错误,但是在代码逻辑中找不到任何错误。有人可以帮助我在我的代码中查找错误。我的代码如下。提前致谢。
package main import "rand" func Routine1(command12 chan int, response12 chan int, command13 chan int, response13 chan int) { for i := 0; i < 10; i++ { y := rand.Intn(10) if y%2 == 0 { command12 <- y } if y%2 != 0 { command13 <- y } select { case cmd1 := <-response12: print(cmd1, " 1st\n") case cmd2 := <-response13: print(cmd2, " 1st\n") } } close(command12) } func Routine2(command12 chan int, response12 chan int, command23 chan int, response23 chan int) { for i := 0; i < 10; i++ { select { case x, open := <-command12: { if !open { return } print(x, " 2nd\n") } case x, open := <-response23: { if !open { return } print(x, " 2nd\n") } } y := rand.Intn(10) if y%2 == 0 { response12 <- y } if y%2 != 0 { command23 <- y } } } func Routine3(command13 chan int, response13 chan int, command23 chan int, response23 chan int) { for i := 0; i < 10; i++ { select { case x, open := <-command13: { if !open { return } print(x, " 2nd\n") } case x, open := <-command23: { if !open { return } print(x, " 2nd\n") } } y := rand.Intn(10) if y%2 == 0 { response13 <- y } if y%2 != 0 { response23 <- y } } } func main() { command12 := make(chan int) response12 := make(chan int) command13 := make(chan int) response13 := make(chan int) command23 := make(chan int) response23 := make(chan int) go Routine1(command12, response12, command13, response13) go Routine2(command12, response12, command23, response23) Routine3(command13, response13, command23, response23) }
谁能告诉我为什么我将Routine2和Routine3声明为go例程,为什么输出为[no output]。我是GO语言的新手,据我从“ http://golang.org/doc/effective_go.html#concurrency ” 了解,go用于在同一地址空间中与其他goroutine并行执行goroutine。所以,问题是所有例程都在运行,但是输出为[no output]。
为了使程序更清晰:我实际上很想做的是在每个例程之间创建两个通道,然后使用一个通道将int发送到另一个通道,并从该例程的另一个通道接收int。例如,例行程序1和3之间的通道是command13和response13。例程1使用command13向例程3发送int,response13从例程3接收int。对于例程3,response13用于向例程1发送int和command13从例程1接收int(命令/响应13代表例程1和例程3之间的通道)。现在,由于三个例程是并发的,并且它们具有特定的例程来处理接收到的味精或发送味精,为什么它们进入死锁状态?
go Routine1(command12, response12,command13, response13 ) go Routine2(command12, response12,command23, response23) // go routine Routine3(command12, response12,command23, response23 )
这将在新的goroutine中启动Routine1,而主goroutine将继续执行下一条语句。因此,Routine1和Routine2将同时执行,但是Routine2将在Routine2完成后启动。您可能会在这里错过另一个“继续”声明。
然后,我试图遵循您的程序。在Routine1中,您可以
command13 <- y
这将阻止Routine1,直到准备好另一个可以接收您的消息的goroutine。因此,您需要y := <-command13在另一个goroutine中使用。
y := <-command13
但是现在,让我们仔细看看其他两个goroutine的参数:
Routine2(command12, response12,command23, response23) Routine3(command12, response12,command23, response23 )
如您所见,所有goroutine都不具有对command13的访问权限(但是您要两次传递command12)。因此,Routine1或Routine2或Routine3均无法继续。僵局!
我建议您回到绘图板上。首先考虑您要做什么,绘制一些有关预期消息流的图表,然后尝试实现该行为。
从那时起,真的很难调试程序,
response23
response13
gofmt
首先,我可以向您推荐Go教程中的“ Prime Numbers”示例。在此示例中,可能的质数从一个goroutine传递到另一个goroutine。此外,此示例还包含一些有关消息流的漂亮图形以及一些非常好的说明。您可能会喜欢。