小编典典

所有goroutine都在睡觉-死锁!\----—错误

go

我想编写三个同时发送整数的并发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之间的通道)。现在,由于三个例程是并发的,并且它们具有特定的例程来处理接收到的味精或发送味精,为什么它们进入死锁状态?


阅读 161

收藏
2020-07-02

共1个答案

小编典典

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中使用。

但是现在,让我们仔细看看其他两个goroutine的参数:

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

如您所见,所有goroutine都不具有对command13的访问权限(但是您要两次传递command12)。因此,Routine1或Routine2或Routine3均无法继续。僵局!

我建议您回到绘图板上。首先考虑您要做什么,绘制一些有关预期消息流的图表,然后尝试实现该行为。

从那时起,真的很难调试程序,

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

首先,我可以向您推荐Go教程中的“ Prime
Numbers”示例。在此示例中,可能的质数从一个goroutine传递到另一个goroutine。此外,此示例还包含一些有关消息流的漂亮图形以及一些非常好的说明。您可能会喜欢。

2020-07-02