英文:
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
thanAdd
: The waitgroup never finishes, and the waiting goroutine halts forever (either panics if all goroutines are deadlocked, or a silent failure otherwise) - Less
Add
thanDone
: panics. SeeWaitGroup.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")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论