go 例程未从通道收集所有对象

2023-12-26

我有一个go-routine将对象添加到通道中,然后我有 4 个go-routines处理通道对象。处理只不过是将对象添加到数组中。但有时,最终数组中会丢失对象。所以我假设在某个时刻通道停止收集对象。我有以下代码:

package main

import (
    "log"
    "sync"
)

func main() {
    j := 0
    for {
        if j == 10 {
            break
        }
        wg := sync.WaitGroup{}
        months := []string{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"}
        hits := make(chan string)
        i := 0
        wg.Add(1)
        go func() {
            defer close(hits)
            for {
                if i == 25 {
                    wg.Done()
                    return
                }
                for _, month := range months {
                    hits <- month
                }
                i++
            }
        }()

        temp := []string{}
        for updateWorker := 1; updateWorker <= 4; updateWorker++ {
            wg.Add(1)
            go func() {
                for hit := range hits {
                    temp = append(temp, hit)
                }
                wg.Done()
                return
            }()
        }

        wg.Wait()

        log.Printf("length of temp %+v\n", len(temp))
        j++
    }
}

我在用sync库来同步例程。我将相同的过程循环 10 次以测试输出是否一致。我期待这样的输出:

length of temp 175

它是 175,因为我发送了 7 个月的字符串 25 次。 但有时输出小于175,不知道为什么。我对 Go 例程有点初学者。那么有人可以帮我找到原因吗?谢谢。


问题是updateWorkergoroutine 都从以下位置收集结果hits通道(到目前为止一切顺利),并且它们都将结果存储到temp局部变数不同步。这是不行的。

从多个 goroutine(其中至少有一个是写入)对所有变量的访问必须同步。

如果您在启用竞争检测器的情况下运行它,它会尖叫着数据竞争(go run -race app.go).

如果减少数量,它会立即产生有效结果updateWorkergoroutine 设为 1,因为这样我们就消除了应用程序的单一数据竞争源:

for updateWorker := 1; updateWorker <= 1; updateWorker++ {
    // ...
}

如果你想保留多个updateWorkergoroutine,它们对共享的访问temp变量必须同步。

With a sync.Mutex https://golang.org/pkg/sync/#Mutex:

var (
    mu   sync.Mutex
    temp []string
)
for updateWorker := 1; updateWorker <= 4; updateWorker++ {
    wg.Add(1)
    go func() {
        for hit := range hits {
            mu.Lock()
            temp = append(temp, hit)
            mu.Unlock()
        }
        wg.Done()
        return
    }()
}

另请注意,在这个简单的示例中,使用多个updateWorker对于 goroutine,添加上述同步(锁定)甚至会使其性能低于仅使用其中之一的性能。

为了正确分配工作和收集结果,请查看以下答案:这是 Go 中惯用的工作线程池吗? https://stackoverflow.com/questions/38170852/is-this-an-idiomatic-worker-thread-pool-in-go/38172204#38172204

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

go 例程未从通道收集所有对象 的相关文章

  • vscode 中的调试不会在断点处停止,调试器启动时显示“无法找到文件...”

    乌班图 vscode 1 62 1 去1 17 3 vscode go 扩展 v0 29 0 深入研究 v1 7 1 我是 vscode 和 Go 的新手 我有多年在 Eclipse 中调试 Java 应用程序的经验 我构建了一个小型多模块
  • 取消用户特定的 goroutine [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一个应用程序 网络应用程序 允许用户使用 twitter oauth 登录并提供自动推文删除功能 用户登录到 Web 应用程序后
  • Golang 按位运算以及一般字节操作

    我有一些 C 代码 可以对字节执行一些按位运算 我正在尝试在 golang 中做同样的事情 但遇到了困难 C 中的示例 byte a c byte data int j c data j c byte c j c a c 0xFF c 0x
  • 何时在多线程中使用 易失性?

    如果有两个线程访问全局变量 那么许多教程都说使该变量成为易失性的 以防止编译器将变量缓存在寄存器中 从而无法正确更新 然而 两个线程都访问共享变量需要通过互斥体进行保护 不是吗 但在这种情况下 在线程锁定和释放互斥体之间 代码位于关键部分
  • 视频第一帧

    我正在创建一个单页应用程序 后端使用 Golang 前端使用 javascript 我想找到一种使用 Golang 获取视频第一帧的方法 首先 我将 mp4 视频文件上传到服务器 它保存在服务器上 有没有办法使用 Golang 获取该视频的
  • 在 IntelliJ IDEA 中运行。多个文件和错误未定义:数据

    我想使用 IntelliJ IDE 社区版编写代码GO Go语言 我安装了正确的插件 并安装了构建应用程序所需的所有工具 我的应用程序包含以下两个文件 每个都在目录中 事件服务器 Main go Data go 如果我想使用 Run Ctl
  • C++ 类内线程并发

    我试图在一个类中运行两个并发线程 它们都使用相同的函数打印数据 使用 std lock guard 进行作用域锁 问题是只有第一个线程被触发 第二个线程永远不会被调用 include
  • 如何在C#中执行Go函数

    有没有办法从 C 执行 Go 函数 例如 对于 Python 我会使用 Ironpython 我知道我可以生成一个进程来执行 Go 脚本 但如果可能的话 我真的不想回退到这样的解决方案 Google 搜索没有显示任何内容 那么有什么方法可以
  • 我可以根据我正在构建的操作系统导入 Golang 包吗?

    假设我有一个基于哪个操作系统的 go 项目 在某些情况下是哪个发行版 我想使用 Systemd 客户端包 Upstart 客户端包 sysv 客户端包 launchd 客户端包 是否可以有选择地导入每个包 以便我只导入我正在构建的每个操作系
  • 完全删除使用“go get”安装的软件包?

    我正在使用 Go 1 13 1 最新版本 我正在尝试完全删除我安装的软件包go get来自 GitHub 这go clean i
  • 在处理程序之后访问 HTTP 请求上下文

    在我的日志记录中间件 链中的第一个 中 我需要访问一些在链下游的某些身份验证中间件中编写的上下文 并且仅在处理程序本身执行之后 旁注 需要首先调用日志记录中间件 因为我需要记录请求的持续时间 包括在中间件中花费的时间 此外 当权限不足时 身
  • Golang中如何删除字符串的最后一个字符?

    我想删除字符串的最后一个字符 但在此之前我想检查最后一个字符是否是 如何才能做到这一点 以下是删除尾随加号的几种方法 package main import fmt strings func TrimSuffix s suffix stri
  • ThreadPoolExecutor 和队列

    我以为使用线程池执行器 http docs oracle com javase 6 docs api java util concurrent ThreadPoolExecutor html我们可以提交Runnables 要在以下位置执行B
  • 并发集合和独特元素

    我有一个并发BlockingCollection具有重复的元素 如何修改它以添加或获取不同的元素 默认后备存储BlockingCollection is a ConcurrentQueue 正如其他人指出的那样 使用它来添加不同的项目相当困
  • 重新插入通道导致死锁

    我有稳定的入站 作业 流 将其输入到无缓冲通道中 我有一个for range循环来迭代项目并处理它们 如果处理该项目失败 我会将项目重新插入通道中 以便稍后重试 问题是当我将项目重新插入通道时 它陷入僵局 我明白为什么会发生这种情况 处理器
  • 为什么 GetThreadTimes 返回

    我试图测量线程中花费的时间以用于进度报告目的 但我从 GetThreadTimes 系统调用中得到非常奇怪的结果 给出以下程序 在 VS 2013 中编译 针对 NET 4 5 using System using System Diagn
  • golang mongodb (mgo) 没有插入文档

    我在使用 mgo 在 mongodb 中保存 golang 结构时遇到问题 type AN Track Log struct Id bson ObjectId bson id omitempty user session id str st
  • 如何确定 fork-join 任务的适当分工阈值

    看完之后分叉 连接教程 http docs oracle com javase tutorial essential concurrency forkjoin html 我创建了一个用于计算大阶乘的类 public class ForkFa
  • Go 编程语言中的“方法需要指针接收器”

    我刚刚看到了 Go 编程语言的演示 并想尝试写几行 一切工作正常 直到我尝试在这种情况下使用界面 我该如何解决这个问题 package main import fmt type entity float32 func e entity in
  • 是否可以使用 go:generate 重定向 stdin/stdout

    我有一个充当管道的工具 它从标准输入读取数据并将源代码写入标准输出 是否可以设置输入 输出重定向并将此类工具与 go generate 一起使用 就像是 go generate tool lt file txt gt file go 我想出

随机推荐

  • nvd3.js:无法将 onClick 事件与 svg 中的数据点绑定

    我试图将数据点与 onclick 事件绑定 以便我可以显示一个带有一些附加详细信息和链接的覆盖框 我正在使用 nv point类来访问数据点 问题是我无法将 onclick 事件注册到这些数据点 这是代码 d3 selectAll nv p
  • Cassandra .csv 导入错误:批量太大

    我正在尝试通过复制命令将数据从 csv 文件导入到 Cassandra 3 2 1 文件中只有 299 行 14 列 我收到错误 无法导入 299 行 InvalidRequest code 2200 无效查询 message 批次太大 我
  • 使用 javascript 更快地选择元素

    我想知道是否有更快的方法来选择它 document getElementById container getElementsByTagName p 0 getElementsByTagName strong 1 innerText 结构是
  • 从基类方法克隆派生类

    我有一个抽象基类Base它具有一些共同的属性 以及许多实现不同逻辑但很少有附加字段的派生属性 public abstract Base protected int field1 protected int field2 protected
  • 获取 x86-64 指令的大小

    我需要一个可以计算 x86 64 指令长度的函数 例如 它可以像这样使用 char ret 0xc3 size t length instructionLength ret length在此示例中将设置为 1 我不想包含整个反汇编库 因为我
  • 编译静态库与标准库的链接(静态)

    我正在尝试编译一个静态库 我们称之为library a 该库消耗标准库的资源 该库可以通过某种方式静态链接标准库 我已经证明了类似的事情 g c library static libstdc o library o ar rcs libra
  • 如何观察目录的变化? [复制]

    这个问题在这里已经有答案了 在 python 核心中找不到任何东西来执行此操作 谁能推荐一个库或 电池 来做到这一点 理想情况下 我希望它是可移植的 但如果它仅适用于 Unix 我的服务器 也没关系 在 Linux 上 您可能对 pyino
  • Reflection.Emit 与 CodeDOM

    使用 Reflection Emit 库与 CodeDOM 在运行时动态生成代码有哪些优缺点 我正在尝试根据运行时以 XML 形式提供的元数据在系统中生成一些 相对复杂的 动态类 我将生成扩展应用程序程序集中现有类的类 实现附加接口 添加方
  • 矢量绘图中的微光动画

    我一直在尝试使用动画矢量可绘制图标实现闪烁动画 我正在寻找的效果与此类似 我已经用过Facebook 微光库 https facebook github io shimmer android 为了获得这种效果 尽管这正是我所需要的 但我想使
  • Typescript Array[T] 接受 {..T} 作为有效类型

    使用时这咬了我useState
  • 检索 Sitecore 项目在内容树中的位置 A 以及位置 B 中的用户

    给定以下内容树 我如何将经销商与汽车关联起来 以便获得这样的 URL http website Dealerships JimWhite 福特 http website Dealerships JimWhite Ford 我需要能够在汽车下
  • 有没有办法在 Kotlin 中使用初始化函数构造 HashSet?

    从文件中读取星星2016 年 Facebook 黑客杯 https www facebook com hackercup problem 910374079035613 Boomerang Constellations问题 可以定义以下扩展
  • 如何调用同步谷歌日历

    首先阅读以下问题 从 Android 上的日历提供程序中删除事件 https stackoverflow com questions 18774394 delete events from calendar provider on andr
  • Eclipse 无法识别字符串和类

    我保存了一个由 eclipse 构建的项目 然后我的电脑就死机了 当我修复它并重新格式化时 我重新下载了 eclipse 等 实际上 当我按下 eclipse exe 时 它会显示 eclipse juno 图标 但窗口的名称是 Java
  • C++“内存屏障”示例[重复]

    这个问题在这里已经有答案了 我正在阅读有关 volatile 关键字的问题的答案 https stackoverflow com a 2485177 997112 https stackoverflow com a 2485177 9971
  • C# 中任意等级数组的索引

    我需要迭代任意排名的数组 这是为了阅读和写作 所以GetEnumerator不管用 Array SetValue object int 不适用于多维数组 Array SetValue object params int 需要过多的算术来迭代
  • 在 git bash 中创建一个新文件

    我已经运行了 Windows 版 Git 但我不确定它是否应该充当文本编辑器 我想我是用 Vim 编辑器安装的 但是在 Git Bash shell 中如何创建文件 例如网页 html git add webpage html 返回为 fa
  • Flutter:如何在手势检测器中禁用 onTap 一段时间?

    我有一个GestureDetector在自定义无状态视图中 什么时候onTap触发后 我显示了一个显示一些信息的小吃店 当用户快速多次单击时 它会永远显示小吃栏 源代码 https github com ammaratef45 zold f
  • Ivy,主配置是什么,为什么它不拉动jvyaml?

    我有以下常春藤文件
  • go 例程未从通道收集所有对象

    我有一个go routine将对象添加到通道中 然后我有 4 个go routines处理通道对象 处理只不过是将对象添加到数组中 但有时 最终数组中会丢失对象 所以我假设在某个时刻通道停止收集对象 我有以下代码 package main