可以将WaitGroup与普通函数一起使用吗?

huangapple go评论87阅读模式
英文:

Can WaitGroup used with normal functions

问题

我可以使用WaitGroup与普通函数一起使用,而不仅仅是与goroutine一起使用吗?

我有以下类型:

type Manager struct {
   ....
   wg sync.WaitGroup
}

func (m *Manager) create() {
    m.wg.Add(1)
    defer m.wg.Done()
    ....
    ....
}
func (m *Manager) close() {
   m.wg.Wait()
}

这对我来说运行良好,我只想知道这是否正确。

英文:

Can I use waitgroup with normal function and not with always goroutines
I have following type

type Manager struct {
   ....
   wg sync.WaitGroup
}

func (m *Manager) create() {
    m.wg.Add(1)
    defer m.wg.Done()
    ....
    ....
}
func (m *Manager) close() {
   m.wg.Wait()
}

It is working for me fine, I just want to know if this is correct

答案1

得分: 1

在并发上下文中,等待组(waitgroup)允许你暂停一个 goroutine,直到组中的任务全部完成。如果你错误地使用等待组,可能会出现以下错误的结果:

  • Done 的数量少于 Add 的数量:等待组永远不会完成,等待的 goroutine 会永远停止(如果所有的 goroutine 都发生了死锁,会引发 panic,否则会静默失败)。
  • Add 的数量少于 Done 的数量:引发 panic。参见 WaitGroup.Add

在非并发的上下文中,你不会从等待组的同步中获得任何好处,所以它唯一的作用就是证明计数器的增加和减少的总量是相等的(在正确使用等待组的情况下)。然而,在使用不正确的情况下,它可能导致静默失败(参见上文),所以不应该以这种方式使用它。

可能存在一种合法的用例,你想要增加/减少一个计数器,并在最后验证它是否解析为 0。在非并发的上下文中,你不需要使用这样一个复杂的工具来实现:只需使用一个 int 变量即可!

例如:

var counter int
// 设置
// vv 等同于 wg.Add
counter += expectedNumberOfActions

for x := range actions {
    // 做一些操作
    // vv 等同于 wg.Done
    counter--
}

// vv 实现了 wg.Wait 的目的
if counter != 0 {
   panic("哦不!计数器没有正确解析。可能在实现中存在一些 bug")
}
英文:

In the concurrent context, a waitgroup allows you to halt a goroutine until the group is "done". If you use the waitgroup incorrectly, you can have these erroneous outcomes:

  • Less Done than Add: The waitgroup never finishes, and the waiting goroutine halts forever (either panics if all goroutines are deadlocked, or a silent failure otherwise)
  • Less Add than Done: panics. See WaitGroup.Add

In the non-concurrent context, you won't receive any benefit from the synchronization of the waitgroup, so the only effect it can really have is demonstrating that the total amount added to the counter and the total amount taken away are equal (as is in correct use of a waitgroup). However, in the case of incorrect usage, it can result in a silent failure (see above), so you should not use it in this way.

There could be a legitimate use case where you want to increment / decrement a counter and then verify that it has been resolved to 0 at the end. In a non-concurrent context, you don't need such a fancy tool to do this: just use an int!

For example:

var counter int
// setup
// vv equivalent to wg.Add
counter += expectedNumberOfActions

for x := range actions {
    // do something
    // vv equivalent to wg.Done
    counter--
}

// vv achieves the purpose of wg.Wait
if counter != 0 {
   panic("oh no! the counter was not resolved correctly. there may be some bug in the implementation")
}

huangapple
  • 本文由 发表于 2021年9月16日 16:31:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/69204966.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定