所有的 goroutine 都在睡觉——僵局! - - - - 错误

2023-12-28

我想编写三个并发的 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)
}

谁能告诉我为什么如果我将例程和例程3声明为goroutine,为什么输出是[无输出]。我是 GO 新手,据我了解,“http://golang.org/doc/ effective_go.html#concurrency http://golang.org/doc/effective_go.html#concurrency”,go 用于与同一地址空间中的其他 goroutine 并行执行 goroutine。那么,问题是什么,所有例程都在运行,但输出是[无输出]。

为了使程序更清晰:实际上我很累的是在每两个例程之间创建两个通道,然后使用一个通道将 int 发送到另一个通道,并通过另一个通道从该例程接收 int。例如,例程 1 和 3 之间的通道是命令 13 和响应 13。例程 1 使用 command13 发送 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 将同时执行,但 Routine3 将在 Routine2 执行完毕后启动。您可能会错过这里的另一个“go”语句。

然后,我试图遵循你的计划。在 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在发布之前先获取源代码:)

作为起点,我可以向您推荐“质数”示例去教程 http://golang.org/doc/go_tutorial.html。在此示例中,可能的素数从一个 Goroutine 传递到另一个 Goroutine。此外,这个示例还包含一些有关消息流的漂亮图形以及一些非常好的解释。你可能会喜欢它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

所有的 goroutine 都在睡觉——僵局! - - - - 错误 的相关文章

  • 如何在 Go 应用程序中处理打开/关闭数据库连接?

    我的 Web API 应用程序中有一组函数 他们对 Postgres 数据库中的数据执行一些操作 func CreateUser db err sql Open postgres user postgres password passwor
  • GoQt 致命错误:QAbstractAnimation:没有这样的文件或目录

    我尝试编译 Qt 来开发桌面应用程序 我按照 Qt 网站上的官方 wiki 指南的说明进行操作 当我尝试go run示例文件夹中的示例 我收到错误 去运行 home pinkya rabbit workspace go1programs s
  • 有没有办法在 VSCode 中保存时运行 go 测试,并将其输出到终端?

    现在我有几个项目在VSCode中运行 运行起来相当繁琐go test每次我编写新代码时 我宁愿立即看看我是否破坏了某些东西 我知道在 Javascript 中我可以在每次保存文件时运行测试 并将输出发送到终端 现在我正在使用 保存时运行 h
  • 展平嵌套结构会导致切片的切片

    所以我有一个像这样的结构 type Bus struct Number string Name string DirectStations Station Station is another struct ReverseStations
  • 如何将UTC时间转换为unix时间戳

    我正在寻找将 UTC 时间字符串转换为 unix 时间戳的选项 我的字符串变量是02 28 2016 10 03 46 PM并且需要将其转换为 unix 时间戳 例如1456693426 知道该怎么做吗 首先 unix时间戳14566934
  • Java 8:并行 FOR 循环

    我听说 Java 8 提供了很多关于并发计算的实用程序 因此我想知道并行给定 for 循环的最简单方法是什么 public static void main String args Set
  • go中有memset的类似物吗?

    在 C 中 我可以使用某些值初始化数组memset https msdn microsoft com en us library aa246471 28v vs 60 29 aspx const int MAX 1000000 int is
  • 在 Go 中初始化嵌入结构

    我有以下内容struct其中包含一个net http Request type MyRequest struct http Request PathParams map string string 现在我想初始化匿名内部结构http Req
  • 复杂数据类型作为 Go 中映射的键

    我正在尝试在 Go 中创建一个由大整数作为键的映射 effective Go 明确指出 结构体 数组和切片不能用作映射键 因为这些类型上没有定义相等性 这是有道理的 我当然可以将大整数转换为字符串并使用字符串作为键 但我在这里寻找更通用的解
  • 如何在golang中解析JSON而不需要解组两次

    我有一个 Web 套接字连接 它在 JSON 对象中发送不同类型的消息 并且我想将内容解组到一些已知的结构中 为此 我认为我应该执行以下操作 步骤 1 将 JSON 解组为通用映射 字符串 接口 步骤 2 找到我要找的钥匙 步骤 3 尝试将
  • “go.tools”的权限被拒绝错误

    当我尝试安装 go 工具时 我的权限被拒绝 usr local go pkg tool linux amd64 cover 我可以接受 因为它是 usr local 目录及需求root使用权 但我的第一个疑问是为什么当我设置时它试图安装在这
  • 在 Gorilla Mux 中嵌套子路由器

    我一直在使用gorilla mux https github com gorilla mux满足我的路由需求 但我注意到一个问题 当我嵌套多个子路由器时它不起作用 这是示例 func main r mux NewRouter StrictS
  • 在 Go 中,如何将结构体转换为字节数组?

    我有一个我定义的结构实例 我想将其转换为字节数组 我尝试了 byte my struct 但这不起作用 另外 我还被指出二进制包 http golang org pkg encoding binary 但我不确定我应该使用哪个函数以及应该如
  • 如何将接口转换为接口切片?

    我的输入是interface 而且我知道它可以是任何类型的数组 我想读取我输入的元素之一 所以我尝试将我的interface 进入一个 interface 但是 go 会给我以下错误 恐慌 接口转换 interface 是 map stri
  • 在 Go to 函数中通过引用和值传递

    我对 Go 中通过引用和值传递有点困惑 我已经看到过对类型前面的 的解释 在类型名称前面 表示声明的变量将存储该类型的另一个变量的地址 而不是该类型的值 类型 这对我来说毫无意义 在Java中 如果我将数据库实例传递给函数 我会这样做 da
  • 在复杂的文件夹结构中进行测试

    我正在 golang 中构建一个设计模式存储库 为了运行所有测试 我使用这个 bash 脚本 有用 bin bash go test creational abstract factory go go test creational bui
  • Golang 结构体初始化

    有一个像这样的简单结构 type Event struct Id int Name string 这两种初始化方法有什么区别呢 e1 Event Id 1 Name event 1 e2 Event Id 2 Name event 2 为什
  • 将产生 goroutine 的 golang 方法

    据我所知 如果 goroutine 太忙 它们会阻止其他 goroutine 运行 对我来说 这意味着我的应用程序的性能和响应能力可能取决于我知道哪些库方法将控制其他 goroutine 例如通常是 Read 和 Write 有什么方法可以
  • container_memory_working_set_bytes 与 process_resident_memory_bytes 和total_rss 之间的关系

    我希望了解以下关系 容器内存工作集字节 vs 进程驻留内存字节 vs 总计RSS 容器内存 rss 文件映射以便更好地配备OOM可能性警报系统 这似乎违背了我的理解 这让我现在感到困惑 如果容器 pod 运行单个进程 执行用 Go 编写的编
  • 有没有办法从另一个包访问结构体的私有字段?

    我在一个包中有一个具有私有字段的结构 package foo type Foo struct x int y Foo 另一个包 例如 白盒测试包 需要访问它们 package bar import foo func change foo f

随机推荐

  • 是否可以在 C++03 中定义等效的“移动和交换习惯用法”

    我有义务C 03我有一个不可复制的对象 例如持有资源 我需要使用移动和交换语义能够做类似的事情并避免复制 MyClass returnMyClass void MyClass temp fill temp members with actu
  • 虚拟地球或谷歌地图

    简单的问题 答案可能不是 我将为客户开发一个 Web 应用程序 ASP NET MVC 他们询问我是否使用 Google 地图或 Virtual Earth 来提供地图解决方案的意见 你会选择哪一个 为什么 或者还有其他可以推荐的吗 还有什
  • 如何从数据帧创建 key:column_name 和 value:python 列中的唯一值的字典

    我正在尝试创建一个键 值对的字典 其中键是数据帧的列名 值将是包含该列中所有唯一值的列表 最终我希望能够从基于条件的字典 到目前为止 这是我能够做的 for col in col list 1 list list append footwe
  • Pytrends 趋势结果与手动下载的数据不相似

    I use pytrends自动下载数据到csv来自谷歌趋势 我使用的代码如下 在本例中 我正在下载 2008 年至今的每月 Google 趋势数据 from pytrends request import TrendReq from ur
  • html 5 canvas 硬件在 android chrome beta 上加速吗?

    我在 Android 浏览器与 chrome beta 上进行了一些 html 5 canvas 测试 结果有利于 Android 默认浏览器 尽管 chrome gpu 显示 canvas 具有硬件加速功能 测试示例 带有 8 个小图像的
  • istream读取失败后

    我有一小段代码来读取用户数据 如下所示 include
  • 在 Java 中,如何录制扬声器的声音输出? [复制]

    这个问题在这里已经有答案了 我有一个 Java 应用程序 它从多个来源接收声音 用户的能力之一是将应用程序中发生的情况记录到 AVI 文件中 我想将声音包含在该视频捕获中 如何录制用户会听到的声音 例如所有声音输入混合在一起的结果 我可以弄
  • 如何确定系统上的 Boost 版本?

    有没有一种快速方法可以确定系统上 Boost C 库的版本 增强信息宏 http www boost org doc libs 1 44 0 libs config doc html boost config boost macro ref
  • Windows ISO 8601 时间戳

    我需要将 Windows PowerShell 中的日期转换为 ISO 8601 格式 在 Linux Unix 中没有问题 TZ 0 date d
  • 从 Android 应用程序向 Azure AD 进行 Firebase 身份验证

    我正在尝试将 Microsoft 登录方法添加到我的 Firebase 项目中 希望允许用户使用其 Azure AD 凭据登录我的 Android 应用程序 我已经完成了使用 电子邮件 密码 提供商的所有设置 该提供商运行良好 我不打算访问
  • 扑动|如何将数据添加到 firestore 中的现有文档

    我正在使用 firestore 来存储我的 flutter 应用程序的数据 并且我创建了一个在用户登录后自动在 firestore 中创建文档的功能 现在我希望用户在填写此表单时 数据将添加到用户电子邮件所在的同一文档中 RaisedBut
  • 为什么节点 contains 方法没有捕获对 svg 元素的点击?

    我有一个基本的模态 其 html 结构中有一个 svg 图标 我想检测模式之外的点击 以便我可以将其关闭 执行此操作的代码类似于以下内容 document addEventListener mousedown e gt if modal c
  • SQLite删除查询错误

    delete N from Tbl Nodes N Data Tree DT WHERE N Part DT Part 对于这个命令我收到以下错误 System Data SQLite SQLiteException SQLite erro
  • 本地网络上的Mysql错误10061

    我正在尝试连接到本地服务器的数据库 位于 192 168 0 198 但我收到 10061 错误 当我尝试连接真正的 putty 然后只是一个普通的 mysql 登录 时 它没有给我带来任何问题 mincraft 插件使用以下命令登录数据库
  • CloudKit错误处理-重试逻辑

    我想在我的应用程序中加入出色的 CloudKit 错误处理功能 就像 Apple 希望我们做的那样 我现在想保存并修改一条记录 这是我的基本保存逻辑 func addNewRecord managedObj NSManagedObject
  • requestIdleCallback 和 setImmediate 之间的区别?

    目前有 2 个不同的 API 旨在将任务分解为预定的回调函数 设置立即 https developer mozilla org en US docs Web API Window setImmediate 非标 请求空闲回调 https d
  • 第一次打开浏览器窗口/选项卡后执行 JavaScript 代码

    有没有一种方法可以在浏览器中的窗口或选项卡打开时仅执行一次 JavaScript 代码 然后在该窗口 选项卡的整个生命周期中不再执行 即使导航离开 一种使用方式window sessionStorage像这样 if window sessi
  • 如何对 url 中的视频进行加密并将加密视频保存到设备的 SD 卡

    在我的应用程序中 我必须使用许多视频文件 所有视频的总大小大约为 500 MB 因此 我必须在第一次安装和运行应用程序时决定我在后台下载视频 并在加密该视频后将其保存到设备的 SD 卡上 当使用视频时 我会解密该视频并使用它 我决定这样做是
  • 动态创建 C# 类或对象

    我有这个结构 public class FirstClass public List
  • 所有的 goroutine 都在睡觉——僵局! - - - - 错误

    我想编写三个并发的 go 例程 相互发送整数 现在 我的代码已正确编译 但是在第一次执行后 它给出错误 所有 goroutine 都在睡觉 死锁 我试图找到错误 但无法找到代码逻辑中的任何错误 任何人都可以帮助我找到代码中的错误吗 我的代码