可以安全地重用sync.WaitGroup吗? [英] Can sync.WaitGroup safely be reused?
问题描述
在调用 Wait()
之后,可以重新使用 sync.WaitGroup
吗?
Can sync.WaitGroup
be reused after Wait()
is called?
func worker(who string, in <-chan int, wg *sync.WaitGroup) {
for i := range in {
fmt.Println(who, i)
wg.Done()
}
}
func main() {
var wg sync.WaitGroup
AIn := make(chan int, 1)
BIn := make(chan int, 1)
go worker("a:", AIn, &wg)
go worker("b:", BIn, &wg)
for i := 0; i < 4; i++ {
wg.Add(2)
AIn <- i
BIn <- i
wg.Wait()
fmt.Println("main:", i)
}
}
此 play.golang.org/p/QLsvA-b4Ae 运行正常,但是可以保证安全吗?文档没有这么说,但是也许我只是偏执.
This play.golang.org/p/QLsvA-b4Ae runs as expected, but is it guaranteed to be safe? The documentation doesn't say so, but maybe I'm just being paranoid.
推荐答案
是的,它很安全.实际上,它甚至比这更安全.您可以同时从多个goroutine中进行 Wait
,并根据您的使用情况互换 Add
和 Done
调用.只要 Add
发生在 Wait
之前,您就应该是安全的.
Yes, it is safe. In fact, it is even safer than that. You can Wait
from multiple goroutines concurrently, and interchange Add
and Done
calls as appropriate for your use case. As long as the Add
happens before the Wait
, you should be safe.
出于好奇,现在 WaitGroup
是通过互斥锁,两个int32s计数器和一个信号量实现的:
Just out of curiosity, right now the WaitGroup
is implemented with a mutex, two int32s counters, and a semaphore:
type WaitGroup struct {
m Mutex
counter int32
waiters int32
sema *uint32
}
这也是一个有趣的测试:
This is also an interesting test:
var wg1, wg2 sync.WaitGroup
wg1.Add(1)
wg1.Done()
wg1.Wait()
fmt.Println(wg1 == wg2) // Prints true
最后,如果您发现这种使用方式有任何问题,请报告,因为这将是一个错误.
Finally, if you do find any issues with that kind of use, please report as it would be a bug.
这篇关于可以安全地重用sync.WaitGroup吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!