所有的程序都处于休眠状态——死锁!——错误



我想写三个并发的go例程,它们相互发送整数。现在,我的代码被正确编译,但是在第一次执行后,它给出了错误"所有的例程都睡着了-死锁!"。我试图找到错误,但我无法在代码逻辑中找到任何错误。谁能帮我找出我的代码的错误。我的代码如下所示。提前谢谢。

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, " 1stn")
        case cmd2 := <-response13:
            print(cmd2, " 1stn")
        }
    }
    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, " 2ndn")
            }
        case x, open := <-response23:
            {
                if !open {
                    return
                }
                print(x, " 2ndn")
            }
        }
        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, " 2ndn")
            }
        case x, open := <-command23:
            {
                if !open {
                    return
                }
                print(x, " 2ndn")
            }
        }
        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例程,为什么输出是[无输出]。我是GO的新手,正如我从"http://golang.org/doc/effective_go.html#concurrency"中理解的那样,GO用于在同一地址空间中与其他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之间的通道)。现在,由于三个例程是并发的,并且它们有特定的例程来处理接收或发送msg,为什么它们会进入死锁?

go Routine1(command12, response12,command13, response13 )
go Routine2(command12, response12,command23, response23) // go routine
Routine3(command12, response12,command23, response23 )

这将在一个新的运行例程中启动Routine1,主运行例程将继续执行下一条语句。因此,Routine1和Routine2将同时执行,但Routine3将在Routine2完成后启动。您可能会错过这里的另一个"go"语句。

然后,我试着遵循你的程序。在Routine1中,

command13 <- y

这将阻塞Routine1,直到有另一个可以接收您的消息的程序准备就绪。因此,您需要在另一个程序中使用y := <-command13

但是现在,让我们仔细看看另外两个例程的参数:

Routine2(command12, response12,command23, response23)
Routine3(command12, response12,command23, response23 )

如您所见,没有一个程序可以访问command13(但是您传递了两次command12)。因此,Routine1、Routine2和Routine3都不能继续运行。僵局!

我建议你从头开始。首先想想你要做什么,画一些关于预期消息流的图表,然后尝试实现该行为。

现在调试你的程序真的很困难,因为

    我不知道你想干什么。没有关于消息流或类似内容的详细描述。事实上,你的代码根本不包含任何文档。
  • 您正在将称为response23的通道传递给称为response13的参数,以此类推。它们很容易混在一起。
  • 所有这些通用名称,如command12等,使得很难理解这个通道应该做什么
  • 这是一个好主意gofmt你的源代码之前,你发布它:)

作为起点,我可以向您推荐Go教程中的"Prime Numbers"示例。在这个例子中,可能的素数从一个程序传递到另一个程序。此外,这个示例还包含一些关于消息流的漂亮图形以及一些非常好的解释。你可能会喜欢的

您已将您的通道声明为阻塞通道。一旦您尝试从其中一个通道发送或接收,该例程将阻塞,直到读取该值或直到它接收到一个值。

例如,在Routine1中,如果您调用command12 <- y,该例程将阻塞,直到其他东西将y拉出通道。command13也是如此。由于您在循环中运行这些发送,并且Routine2Routine3同步运行,因此遇到了死锁问题。

正如您所发现的,通道和例程都不能保证不会死锁。相反,它们通常用于同步和协调并发执行程序的不同部分。

如果Routine2Routine3也是goroutine,那么没有什么可以阻止你的程序终止——这就是为什么在这种情况下你没有输出。

坐在一张纸上,画出程序中各个元素之间的相互作用可能是有益的。

相关内容

  • 没有找到相关文章

最新更新