我怎么知道我的所有 goroutine 确实正在使用 golang 的同步包等待一个条件

2024-05-14

我有一个应用程序,我正在创建多个 goroutine 来同时执行某个任务。所有工作协程都会等待条件/事件发生,一旦事件被触发,它们就会开始执行。创建完所有goroutines后,主线程在发送广播信号之前应该知道所有goroutines确实处于等待状态。

我知道这可以使用通道来完成(这是推荐的),但我也发现 go 的同步包很有趣。只是想弄清楚如何使用同步包而不是通道来实现相同的功能

package main

import (
    "fmt"
    "sync"
    "time"
)

var counter int

func worker(wg *sync.WaitGroup, cond *sync.Cond, id int) {
    fmt.Println("Starting Goroutine ID:", id)
    // Get a lock and wait
    cond.L.Lock()
    defer cond.L.Unlock()
    fmt.Println("Goroutine with ID: ", id, "obtained a lock")
    // Do some processing with the shared resource and wait
    counter++
    wg.Done()
    cond.Wait()
    fmt.Println("Goroutine ID:", id, "signalled. Continuing...")
}

func main() {
    var wg sync.WaitGroup
    cond := sync.NewCond(&sync.Mutex{})
    counter = 0
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go worker(&wg, cond, i)
    }

    wg.Wait() // Wait()'ing only until the counter is incremented
    // How to make sure that all goroutines you created are indeed wait()'ing ?????
    cond.Broadcast()
    time.Sleep(2 * time.Second)
    cond.Broadcast()
    fmt.Println("Final value of the counter is", counter)
}

如果我在最后 3 行中不使用以下语句(fmt.Println 除外)

    time.Sleep(2 * time.Second)
    cond.Broadcast()

我得到以下输出..

Starting Goroutine ID: 4
Goroutine with ID:  4 obtained a lock
Starting Goroutine ID: 3
Goroutine with ID:  3 obtained a lock
Starting Goroutine ID: 1
Goroutine with ID:  1 obtained a lock
Starting Goroutine ID: 0
Goroutine with ID:  0 obtained a lock
Starting Goroutine ID: 2
Goroutine with ID:  2 obtained a lock
Final value of the counter is 5
Goroutine ID: 3 signalled. Continuing...

理想情况下,每个 goroutine 都应该能够打印

Goroutine ID: 3 signalled. Continuing...

以及相应的 goroutine id。我们无法打印它,因为并非所有 goroutine 都发出信号,因为其中一些 goroutine 甚至没有处于等待状态。这就是我添加 time.Sleep 的原因,这不是一个实际的解决方案。

我的问题是..我怎么知道所有的goroutine实际上都在等待条件cond.Wait()..Channels是一个解决方案,但我想知道如何使用go的sync包来做到这一点?


你有一个问题是Broadcast不保证唤醒所有的 goroutine,因为它只会唤醒已经在等待的 goroutine,并且之间有一个小窗口wg.Done() and cond.Wait()。通常,条件变量将与表示您用于同步的“条件”的变量一起使用。在这种情况下,您可以有一个bool包变量,指示 goroutine 是否可以继续。main会设置它,然后进行广播来告诉 goroutine 继续。例如:

package main

    import (
    "fmt"
    "sync"
)

var counter int
var start bool

func worker(wg *sync.WaitGroup, cond *sync.Cond, id int) {
    fmt.Println("Starting Goroutine ID:", id)
    // Get a lock and wait
    cond.L.Lock()
    fmt.Println("Goroutine with ID: ", id, "obtained a lock")
    // Do some processing with the shared resource and wait
    counter++
    if !start {
        cond.Wait()
    }
    cond.L.Unlock()
    fmt.Println("Goroutine ID:", id, "signalled. Continuing...")
    wg.Done() // Worker is completely done
}

func main() {
    var wg sync.WaitGroup
    cond := sync.NewCond(&sync.Mutex{})
    counter = 0
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go worker(&wg, cond, i)
    }

    cond.L.Lock()
    start = true
    cond.Broadcast()
    cond.L.Unlock()

    wg.Wait() // Wait until all workers are done
    fmt.Println("Final value of the counter is", counter)
}

添加的start变量使得 goroutine 不可能在以下情况下停止继续:main告诉他们。

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

我怎么知道我的所有 goroutine 确实正在使用 golang 的同步包等待一个条件 的相关文章

  • golang sql 驱动程序的准备语句

    关于golang的sql driver 下面两条语句有什么区别 store DB is sql DB type rows err store DB Query SQL args err nil defer rows Close and st
  • Java 中具有可重入锁和条件的生产者消费者场景

    我使用可重入锁和条件编写了一个生产者消费者程序 它工作正常 但我不太确定实施是否正确 此外 它似乎不是最佳的 有人可以验证这是否是正确的实现 此外您能告诉我如何优化它 比如 在真正需要的地方锁定 public class TestRL st
  • Bash脚本无法执行Go命令

    我正在尝试编写一个 bash 脚本来自动在不同的目录中运行 go get install 相关部分在这里 cd web go get cd web go install cd services go get cd services go i
  • 无法理解 5.6.1。注意事项:捕获迭代变量

    我正在学习 Go 但无法理解 var rmdirs func for dir range tempDirs os MkdirAll dir 0755 rmdirs append rmdirs func os RemoveAll dir NO
  • 在并行任务与异步任务上使用 Task.Wait

    在章节中4 4 动态并行性 在史蒂芬 克利里的书中C 中的并发食谱 它说如下 并行任务可能会使用阻塞成员 例如Task Wait Task Result Task WaitAll 和 Task WaitAny 相比之下 异步 任务应该避免阻
  • Go SQL查询不一致

    我在执行查询时遇到一些非常奇怪的不一致 并且想知道是否有人知道原因 想象一下我有一个定义如下的结构 type Result struct Afield string db A Bfield interface db B Cfield str
  • Golang - 更改 Windows 上的构建工作路径

    我正在使用 SublimeText3 GoSublime 插件 在 Windows 8 上测试简单的 Go 程序 go run v example go 在运行之前它正在内部编译 应用程序数据 本地 温度 目录 我的防病毒程序认为这是病毒并
  • 我应该在请求中创建 executorService 还是在 Web 应用程序中共享一个实例?

    我正在向基于 Jersey 的 Web 服务添加一个新端点 支持端点的逻辑需要对另一个服务进行 10 到 50 次调用 这些调用是独立的并且可以并行化 因此我正在考虑使用执行器服务将工作分配到多个线程 我想知道是否应该为每个请求实例化一个
  • 如何在 Goji (Golang) 中使用不同的中间件创建单独的路由组?

    我正在使用Goji https github com zenazn goji https github com zenazn goji 并希望定义具有自己的中间件的路由组 例如 下面的所有路径 company应使用 LDAP 身份验证并定义
  • 给定方法值,获取接收者对象

    Go 有没有办法从方法值获取接收者对象 例如有没有这样的MagicFunc这将使以下程序输出字符串my info来自底层 Foo 实例 package main import fmt type Foo struct A string fun
  • 共享来自单独命令/进程的属性

    我提供带有多个命令和子命令的命令行工具 我使用cobra https github com spf13 cobra命令行 我有两个单独的命令首先是前提条件e 给其他人 例如第一个命令是通过创建临时文件夹并验证某些文件来首选环境 第二个命令应
  • 是否支持动态变量?

    我想知道Go中是否可以动态创建变量 我在下面提供了一个伪代码来说明我的意思 我将新创建的变量存储在切片中 func method slice make type for i 0 i lt 10 i var variable i i slic
  • 何时在多线程中使用 易失性?

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

    我有以下代码 statement SELECT id from source where mgmt 1 var exists string errUnique dr db QueryRow statement mgmt Scan exist
  • nsq 无法通过连接到 nsqlookupd 来消费消息

    我尝试使用 docker compose 来运行 nsq docker compose yml如下 version 3 services nsqlookupd image nsqio nsq command nsqlookupd ports
  • 如何在 Golang 中将 []byte XML 转换为 JSON 输出

    有没有办法在 Golang 中将 XML byte 转换为 JSON 输出 我有以下功能body is byte但我想在一些操作之后将此 XML 响应转换为 JSON 我试过了Unmarshal in xml打包没有成功 POST func
  • ThreadPoolExecutor 和队列

    我以为使用线程池执行器 http docs oracle com javase 6 docs api java util concurrent ThreadPoolExecutor html我们可以提交Runnables 要在以下位置执行B
  • 重新插入通道导致死锁

    我有稳定的入站 作业 流 将其输入到无缓冲通道中 我有一个for range循环来迭代项目并处理它们 如果处理该项目失败 我会将项目重新插入通道中 以便稍后重试 问题是当我将项目重新插入通道时 它陷入僵局 我明白为什么会发生这种情况 处理器
  • Golang中如何获得100%的代码覆盖率? [复制]

    这个问题在这里已经有答案了 我无法获得 100 的代码覆盖率 因为我无法在 Golang 中测试 Fatals 我发现了一些问答 包括this one https stackoverflow com questions 30688554 h
  • 编写每个处理程序中间件

    我希望从处理程序中提取一些重复的逻辑 并将其放入一些每个处理程序的中间件中 特别是 CSRF 检查 检查现有会话值 即身份验证或预览页面 等 我读了关于此的几篇文章 http justinas org writing http middle

随机推荐

  • 如何在 iOS 中设置视图的最大宽度?

    我的应用程序有一个基本的登录屏幕 一个外框以及其中的一些文本字段和按钮 我将框设置为填满屏幕 然而 在某些设备上这个盒子会太大 如何设置视图的最大宽度和高度 您可以使用自动布局约束 使框适应屏幕尺寸 但不超过给定的宽度和高度 为此 请对宽度
  • NodeJS 在目录中递归地哈希文件

    我能够实现目录中的递归文件遍历 即探索目录中的所有子目录和文件 为此我使用了answer https stackoverflow com questions 5827612 node js fs readdir recursive dire
  • Android Camera.takePicture() 有时不返回?

    我正在编写一个Android 拍照应用程序 该代码在 onPreviewFrame byte data Cameracamera 中从预览中获取帧后进行一些处理 问题在于 android hardware Camera 的函数 takePi
  • 关于 C 中的 switch{} 情况?

    我正在读一些文字C language 文字说switch case只能接受整数类型 我只是好奇为什么switch case不接受其他类型 例如浮点数或字符串 这背后有什么原因吗 多谢 经典的原因可能是对于整数值的 决策表达式 可以进行非常好
  • java程序有多少种结束方式?

    我知道使用 System exit 0 可以结束一个java程序 例如 如果我有一个JFrame窗口 它会关闭并结束程序 但我想知道还有多少其他方法 可以关闭它并结束程序 包括发生错误时 程序会被关闭 JFrame也会被关闭吗 添加到其他答
  • 在 UIView 中绘制彩色文本 -drawRect: 方法

    我正在尝试在我的中绘制彩色文本UIView子类 现在我正在使用单视图应用程序模板 用于测试 除了以下内容外 没有任何修改drawRect method 文本已绘制 但无论我将颜色设置为什么 它始终是黑色的 void drawRect CGR
  • Facebook Graph API 中不支持 get 请求

    由于某种原因我的https graph facebook com 210155825774263 https graph facebook com 210155825774263返回错误 error message Unsupported
  • AttributeError:'function'对象在pandas中没有属性'bar'

    我有一个 pandas 数据框 它是 pandas 数据框类型 如下所示 type df Out 176 pandas core frame DataFrame 但是 当我尝试在此数据框上使用任何绘图函数 如条形图 时 会出现如下错误 df
  • 无法解析类型“Microsoft.ApplicationInsights.TelemetryClient”的服务

    我已将我的 Web 项目从 RC1 迁移到 RC2 但出现以下错误 无法解析类型的服务 尝试时出现 Microsoft ApplicationInsights TelemetryClient 启用 Microsoft Application
  • OSX/Mac 中的插件持久设置

    我无法找到在 Mac 上存储 Office js 加载项的持久设置的方法 在 Windows 上 localStorage 工作得非常完美 因为它可以保存关闭和打开 Word 时仍保留的设置 在 Mac 上 localStorage 不会持
  • Cordova - 启动后出现白屏,控制台中没有例外

    我已经离开我的 Cordova 应用程序一段时间了 但昨天刚刚进行了一次新的克隆 发现它出现了 死机白屏 症状 启动画面显示 程序加载 然后我就得到一个空白屏幕 更多细节 CLI 科尔多瓦 6 1 1 安卓 5 1 1 ios 4 1 1
  • 为什么 { } 初始化需要 Add 方法?

    要使用这样的初始化语法 var contacts new ContactList Dan email protected cdn cgi l email protection Eric email protected cdn cgi l e
  • 将对象的值插入到span标签中

    我有一个对象 message text Here is some text 我想将它插入到一个跨度标签中 如下所示 span message text span 这不会打印 这是一些文本 而是只会在网页上显示 message text 我怎
  • 虚拟回调接口

    在 Eclipse 为您创建的来自 Google 的示例主从流代码中 片段中包含以下内容 private Callbacks mCallbacks sDummyCallbacks public interface Callbacks pub
  • 连接数组时合并两个 yaml 文档

    我想合并两个 yaml 文档 结果包含 所有映射值 最后一个优先 串联数组 例如给定这个文件 file1 yml animals elephant donkey flavours sour lemon sweet chocolate str
  • 仅当环境变量具有特定值时如何设置 Apache 标头

    我想在我的 Apache 2 4 配置中设置标头 但前提是环境变量具有特定值 SetEnv ENV NAME prod 我如何仅在以下情况下设置此标头ENV NAME is not prod Header set X Robots Tag
  • 如何使用放心的方式在正文中发送 JsonObject 以进行 post 请求?

    我有一个使用 Google Gson 创建的 JsonObject JsonObject jsonObj gson fromJson response1 json JsonElement class getAsJsonObject 我还对现
  • 设置 IRQ 映射

    我正在遵循一些教程和参考文献来尝试设置我的内核 我在教程中遇到了一些不熟悉的代码 但根本没有解释它 这是我被告知映射的代码16 IRQs 0 15 到 ISR 地点32 47 void irq remap void outportb 0x2
  • 哪里可以找到可靠的 K-medoid(不是 k-means)开源软件/工具? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在学习 K medoids 算法 所以如果我提出不恰当的问题 我很抱歉 据我所知 K medoid
  • 我怎么知道我的所有 goroutine 确实正在使用 golang 的同步包等待一个条件

    我有一个应用程序 我正在创建多个 goroutine 来同时执行某个任务 所有工作协程都会等待条件 事件发生 一旦事件被触发 它们就会开始执行 创建完所有goroutines后 主线程在发送广播信号之前应该知道所有goroutines确实处