如何获取与WaitGroup关联的goroutine数量?

8
假设我使用`WaitGroup`让应用程序的主线程等待我从该主线程启动的所有goroutine完成。那么,有没有一种安全、简单的方法,在任何时间点评估与该`WaitGroup`相关联的goroutine 中仍在运行的数量?
2个回答

18

WaitGroup 的内部状态没有暴露,而且不会被暴露:https://github.com/golang/go/issues/7202

我不认为我们有可能使这个 API 更加复杂。我没有看到除了简单地打印它们之外,可以使用计数器和等待者而不受竞态条件影响的方法。对于那个你可以维护自己的计数。

你可以自己实现一个计数器:

type WaitGroupCount struct {
    sync.WaitGroup
    count int64
}

func (wg *WaitGroupCount) Add(delta int) {
    atomic.AddInt64(&wg.count, int64(delta))
    wg.WaitGroup.Add(delta)
}

func (wg *WaitGroupCount) Done() {
    atomic.AddInt64(&wg.count, -1)
    wg.WaitGroup.Done()
}

func (wg *WaitGroupCount) GetCount() int {
    return int(atomic.LoadInt64(&wg.count))
}

// Wait() promoted from the embedded field

然而,即使计数器访问是同步的,在你读取它之后,它也会立即变得过时,因为其他goroutine可能会继续调用AddDone,无论你使用计数做什么 - 除非你同步依赖于计数的整个操作。但是在这种情况下,你可能需要一个更复杂的数据结构。


1
是的,Golang 的作者们有些奇怪的想法。能够读取数字对于调试非常有用。 - Alexis Wilke

3

有没有一种安全、简单的方法,在任何时候评估与所述waitgroup相关联的goroutine的数量仍在运行?

不,没有。

这是因为Go(语言)没有“与waitgroup相关联的goroutine”的概念。


或者说:使用 wg.Add(1) 和 wg.Done() 监控给定 waitgroup 中添加的 goroutines 数量。 - Serge Hulne
1
@SergeHulne wg.Add(n) 在 goroutine 上不起作用。goroutine 没有真正的身份。wg.Add(n) 将 n 添加到内部计数器,但这不一定对应于一个 goroutine。您是否真正关心的是 goroutine 而不是当前 Waitgroup 计数? - Volker
好的,如何构建一个解决方案来访问内部计数器(getter),或者如何模拟该计数器:每个Add() / Done()对都会增加/减少整数(在互斥体内)是否能解决问题? - Serge Hulne
3
blackgreen的回答已经包含了所有需要知道的内容。WaitGroup的内部细节是不可见的,你无法获取它们。如果你想记录发生了什么(从而了解WaitGroup的状态),你需要自己实现。通常的做法是通过包装WaitGroup、捕获Add和Done操作并维护自己的计数器来实现。 - Volker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接