Go 中的简单工作池

2024-01-02

我正在尝试在 go 中实现一个简单的工作池,但不断遇到问题。我想做的就是让一定数量的工人先完成一定数量的工作,然后再做更多的工作。我正在使用的代码类似于:

    jobs := make(chan imageMessage, 1)
    results := make(chan imageMessage, 1)

    for w := 0; w < 2; w++ {
        go worker(jobs, results)
    }

    for j := 0; j < len(images); j++ {
        jobs <- imageMessage{path: paths[j], img: images[j]}
    }
    close(jobs)

    for r := 0; r < len(images); r++ {
        <-results
    }
}

func worker(jobs <-chan imageMessage, results chan<- imageMessage) {
    for j := range jobs {
        processImage(j.path, j.img)
        results <- j
    }
}

我的理解是,这应该创建 2 个工人,一次可以做 1 件“事情”,并且当他们完成这 1 件事情时,他们将继续获得更多的工作,直到没有其他事情可做。但是,我得到fatal error: all goroutines are asleep - deadlock!

如果我将缓冲区设置为像 100 这样的大值,这可以工作,但我希望能够限制一次完成的工作。

我觉得我很接近,但显然缺少一些东西。


问题是你只是开始“耗尽”results频道,一旦您成功发送了频道上的所有作业jobs渠道。但为了让您能够发送所有作业,无论是jobs通道必须有足够大的缓冲区,或者工作协程必须能够从中消耗作业。

但是,worker goroutine 在使用一项工作时,在执行下一项工作之前,会将结果发送到results渠道。如果缓冲区的results通道已满,发送结果会阻塞。

但最后一部分——工人 goroutine 在发送结果时被阻止——只能通过从results通道 – 在您可以发送所有作业之前,您不需要这样做。死锁如果jobs频道和results频道不能容纳你所有的工作。这也解释了为什么如果将缓冲区大小增加到一个大值,它就会起作用:如果作业可以放入缓冲区,则不会发生死锁,并且在所有作业都成功发送后,您的最终循环将耗尽results渠道。

解决方案?在它自己的 goroutine 中运行生成和发送作业,这样您就可以开始从results“立即”通道,无需等待发送所有作业,这意味着工作协程在尝试发送结果时不会永远被阻塞:

go func() {
    for j := 0; j < len(images); j++ {
        jobs <- imageMessage{path: paths[j], img: images[j]}
    }
    close(jobs)
}()

尝试一下去游乐场 https://play.golang.org/p/jvitOGmzpl.

另请查看类似的实现这是 Go 中惯用的工作线程池吗? https://stackoverflow.com/questions/38170852/is-this-an-idiomatic-worker-thread-pool-in-go/38172204#38172204

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

Go 中的简单工作池 的相关文章

  • ASP.NET 开发人员真的需要关心线程安全吗?

    我认为自己了解线程的概念以及为什么某些代码是或不是 线程安全 的 但作为主要使用 ASP NET 的人 线程和线程安全是我很少考虑的事情 然而 我似乎在 Stack Overflow 上遇到了大量评论和答案 不一定适用于 ASP NET 大
  • 进度条没有进展

    我有一个正在更新 sqlserver 中的表的程序 我有一个表单 我想显示其进度 进度条正在递增 但没有显示 我需要为此使用后台工作者吗 我正在做什么的例子 public void updateTable string tableName
  • 临时表是线程安全的吗?

    我正在使用 SQL Server 2000 它的许多存储过程广泛使用临时表 数据库的流量很大 我担心创建和删除临时表的线程安全性 假设我有一个存储过程 它创建了一些临时表 它甚至可以将临时表连接到其他临时表等 并且还可以说两个用户同时执行存
  • 我应该避免在 golang 中使用单例包吗?

    现在我有一个包裹store包含以下内容 package store var db Database func Open url string error open db connection func FindAll model inter
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • 如何在 Go 中从 stdin 解析无限 json 数组?

    我正在尝试编写一个 i3status 的小替代品 一个与 i3bar 兼容的小程序进行通信this http i3wm org docs i3bar protocol html协议 他们通过标准输入和标准输出交换消息 两个方向的流都是一个无
  • 数据库锁定在 WAL 模式下,只有读取器

    在中使用System Data Sqlite 1 0 86 0 包括SQLite 3 7 17 预写式记录 http www sqlite org wal html模式下 我在并发读取时遇到数据库锁 如果我正确理解 WAL 则不应该出现这种
  • 并发访问且不受数据结构的影响

    问题是这样的 我有一个包含 500 个指针的数组 它们指向双向链表中的 500 个元素 有 10 个并行运行的线程 每个线程运行 50 个循环 并尝试释放列表中的某些元素 该列表已排序 包含简单整数 并且有 10 个其他线程并行运行 搜索包
  • 如何处理或避免BlockedIndefinitelyOnSTM异常?

    我花了很多时间来解决我正在处理的应用程序中遇到的问题 该应用程序是一个 Web 应用程序 使用 scotty 公开 REST 端点 它使用一个TVar保持其更新的状态STM a由前端层触发的动作 由于该应用程序基于事件溯源原则 因此业务层生
  • 如何处理 MSTest 中的 currentDomain.UnhandledException

    我尝试根据答案实施解决方案单元测试时如何处理其他线程引发的异常 https stackoverflow com a 934604 518530 但我仍然不明白在处理程序中要做什么 假设我有一个测试 TestMethod void Test
  • 从子线程绘制到窗口

    我的应用程序从工作线程绘制图形已有 10 多年了 而且我从未遇到过任何问题 工作线程吸引到我的HWND 由主线程创建 如下所示 hdc GetDC hwnd SetDIBitsToDevice or StretchDIBits Releas
  • 使用ftplib进行多线程上传

    我正在尝试进行多线程上传 但出现错误 我猜想也许不可能在 ftplib 中使用多线程 这是我的代码 class myThread threading Thread def init self threadID src counter ima
  • 从创建 UI 的同一线程更新 VCL。为什么?

    我知道我必须调用 Synchronize 来从未创建控件或向窗口发送消息的线程更新 vcl 我经常听到 线程不安全 这个词 但我找不到关于正在发生的事情的实际解释 我知道应用程序可能会因访问冲突而崩溃 但我又不知道为什么 请阐明这个主题 V
  • 可升级读锁的优点?

    我想知道使用可升级读锁与执行这些步骤相比有什么优势 获取读锁 检查条件以查看是否需要进行写锁定 释放读锁 采取写锁定 执行更新 释放写锁 与获取可升级读锁相比 执行上述步骤的一个明显缺点是 步骤 3 和步骤 4 之间存在一个时间窗口 其中另
  • Java 唤醒休眠线程

    我阅读了其他帖子 但没有找到我正在寻找的确切答案 所以我希望有人能给出一些澄清 我有一个将运行一段时间的程序 我有一些在后台运行的线程来执行各种任务 为了简单起见 让我们考虑 3 个线程 ThreadA每 10 秒执行一次任务 其中Thre
  • 我们可以有虚假中断吗?

    我正在创建一个任务轮询器 每分钟都会查找任务 它看起来像这样 public class Poller private final ExecutorService e Executors newSingleThreadExecutor pub
  • 理解 C++11 中的 std::atomic::compare_exchange_weak()

    bool compare exchange weak T expected T val compare exchange weak 是 C 11 中提供的比较交换原语之一 它是weak即使对象的值等于 它也会返回 falseexpected
  • 排序线程按照它们创建/启动的顺序运行

    我如何按照线程实例化的顺序对线程进行排序 我怎样才能让下面的程序按顺序打印数字1 10 public class ThreadOrdering public static void main String args class MyRunn
  • 每个托管线程是否都有自己对应的本机线程?

    我想知道是否在 Net 中创建托管线程 通过调用Thread Start 导致在后台创建一个本机线程 那么托管线程是否有对应的本机线程呢 如果是 当托管线程等待或睡眠时 是否意味着相应的本机线程也在等待或睡眠 是的 NET 线程映射到所有当
  • volatile、final 和synchronized 安全发布的区别

    给定一个带有变量 x 的 A 类 变量 x 在类构造函数中设置 A x 77 我们想将 x 发布到其他线程 考虑以下 3 种变量 x 线程安全 发布的情况 1 x is final 2 x is volatile 3 x 设定为同步块 sy

随机推荐

  • System.Data.OracleClient 不适用于 64 位 Oracle 客户端

    我设计了一个 C 应用程序来连接到 Oracle 数据库并更改架构用户密码 我的参考程序集是来自以下位置的 System Data OracleClient C Program Files x86 Reference Assemblies
  • Rails 4 中的 has_many 'conditions' 选项相当于什么?

    有人能告诉我在 Rails 4 中执行以下行的等效方法是什么吗 has many friends through gt friendships conditions gt status accepted order gt first nam
  • MSBuild - 如何复制可能存在或不存在的文件?

    我遇到一种情况 我需要在 MSBuild 脚本中复制一些特定文件 但它们可能存在也可能不存在 如果它们不存在也没关系 我就不需要它们了 但标准
  • 在未知的 NSMutableArray 深度中搜索值

    好吧 我问了错误的问题 所以我编辑了原来的问题 我将数组存储在数组中 以及 NSDictionaries 它是一种实用程序类型的应用程序 没有固定的结构 用户可以根据需要输入嵌套信息 理想情况下 我需要一种方法来滚动浏览给定参数 一种类的类
  • Cordova Android 状态栏设置为透明

    我正在尝试使用下面的这个插件将状态栏设置为透明 但我无法实现它 我可以将其更改为不同的颜色 但不透明 https github com apache cordova plugin statusbar https github com apa
  • 下载旧版本的 Google App Engine SDK

    在哪里可以找到下载旧版 GAE SDK 例如 1 9 15 我需要找出覆盖范围 也许使用第 3 方 API 该 API 与最新版本不能很好地配合 这取决于相应的 SDK 是否仍受官方支持 这两种类型都可以在appengine sdks ht
  • 使用文本框输入在画布上移动对象

    我有一个画布 可以在上面添加图层 这些图层可以移动 选择 旋转 调整大小等 在画布下方 我显示图层的属性 x y 宽度 高度 我想做的是 当我更改包含 x 和 y 坐标的文本框中的值时 图层应该重新定位到我输入的坐标 我已经尝试了几件事 但
  • 在 Windows 中更改 Python 3 中的“区域设置首选编码”

    我正在使用 Python 3 最近从 Python 2 切换而来 我的代码通常在 Linux 上运行 但有时 不经常 在 Windows 上运行 根据 Python 3 文档open https docs python org 3 libr
  • 以编程方式单击时突出显示 TextView

    我动态生成 TextView 其工作方式类似于按钮 现在我想在他们受到压力时突出显示他们 比如更改文本颜色或背景颜色 我尝试过使用选择器 但它不起作用
  • 如何设置 PowerShell Cmdlet 的默认输出格式?

    我正在 C 中创建一个 PowerShell Cmdlet 以从 JSON 文件读取字段并输出一些对象 这些对象是简单的 POCO 类型 public class FieldDefinition public FieldDefinition
  • C#动态编译字符串和.cs文件

    我正在开发一个网站 用户可以在该网站上针对浏览器文本区域中的问题实现 C 代码解决方案并提交 然后 服务器将将该代码与我在服务器上提供的预定义接口一起编译 将其视为一种策略设计模式 我提供一个策略接口 由用户实现 所以我需要在运行时一起编译
  • 部分排序数组,最后 n 个元素已排序?

    有没有办法对数据数组执行部分排序 以便对最后 n 个元素进行排序 我的意思是使用标准库 而不是实现我自己的排序函数 这就是我现在正在做的事情 示例输出 使用较少的比较器 2 1 4 5 6 8 10 之后的元素 都大于之前的元素 但仅限于右
  • 共享一个控制器的角度多条路线

    我不确定我是否正确处理了这个问题 但我正在构建一个电子商务网站 该网站的一部分有 6 个不同的产品网格页面 每个页面都可以使用相同的视图 ul class products row li class product thumbnail co
  • ASP.NET / Web.config:customErrors 仅在 404 上重定向

    我有这样的场景 用户访问我的网站并点击不再存在的链接 他应该被重定向到自定义错误页面 这样可行 如果用户执行某些操作 引发错误 他应该看到堆栈跟踪和真正的错误页面 这是我当前的 Web config
  • 使用 PHP 文件功能在另一台服务器上创建文件

    我的一台服务器上有一个脚本 我希望该脚本使用 PHP 在我的另一台服务器上创建一个文件 而不是通过 FTP 有很多方法可以做到这一点 我自己会选择第一个 因为它最容易设置 如果你有PHP 另一台服务器上的Apache 只需使用以下命令调用另
  • 将 pfx 格式转换为 p12

    我需要导出一个 pfx将证书格式 来自 Windows MMC 转换为 p12在另一个应用程序中使用 我找不到办法做到这一点 任何人都可以建议一个方法吗 p12 and pfx都是 PKCS 12 文件 我错过了什么吗 您是否尝试过重命名导
  • 从父子表生成字符串树分支

    我有一个父子表 如下所示 child father H G F G G D E D A E B C C E 我希望 sql server 生成类似的东西 正如这个问题中所问的那样 将一系列父子关系转化为层次树 https stackover
  • Angular 2.x 在 body 标签上绑定类

    由于 Angular 2 x 是在主体内部引导的 我该如何添加 class fixed isFixed 在 body 标签上 在我的应用程序之外
  • 匹配不带引号的逗号的正则表达式

    我正在使用 Clojure 所以这是在 Java 正则表达式的上下文中 这是一个示例字符串 a ab cd efg b ab def egf c Conjecture 重要的位是每个字符串后面的逗号 我希望能够使用Java的replaceA
  • Go 中的简单工作池

    我正在尝试在 go 中实现一个简单的工作池 但不断遇到问题 我想做的就是让一定数量的工人先完成一定数量的工作 然后再做更多的工作 我正在使用的代码类似于 jobs make chan imageMessage 1 results make