[英]How do you make sure goroutines finish in a for-loop using WaitGroup?
I'm running a function in a goroutine each time a for-loop iterates, and I'm using sync.WaitGroup
to make sure the goroutines all finish. 每次for循环迭代时我都会在goroutine中运行一个函数,而我正在使用
sync.WaitGroup
来确保goroutine都完成了。 However, I'm getting weird behavior testing the concurrency with counters. 但是,我正在用计数器测试并发性的奇怪行为。 In the example below, I attempt to keep track of the thread count using 4 different techniques (
w
, x
, y
, z
), and get 4 different results. 在下面的示例中,我尝试使用4种不同的技术(
w
, x
, y
, z
)跟踪线程数,并获得4种不同的结果。 The only result I understand is x
, since it is incremented in the for-loop itself. 我理解的唯一结果是
x
,因为它在for循环中递增。 What am I missing here? 我在这里错过了什么?
package main
import "fmt"
import "sync"
var w = 0
func main() {
x := 0
y := 0
z := 0
var wg sync.WaitGroup
for i := 0; i < 10000; i++ {
wg.Add(1)
x++
go func() {
z++
test(&y)
wg.Done()
}()
}
wg.Wait()
fmt.Println(w, x, y, z) // 8947 10000 8831 8816
}
func test(y *int) {
w++
*y++
}
The sync.Waitgroup
is working as expected. sync.Waitgroup
按预期工作。 w
, y
and z
will not reach 10000 because multiple goroutines are incrementing them concurrently, and Go's increment is not concurrent-safe: it is implemented as a normal fetch-increment-reassign operation. w
, y
和z
将不会达到10000,因为多个goroutine同时递增它们,并且Go的增量不是并发安全的:它被实现为正常的fetch-increment-reassign操作。
You have two options. 你有两个选择。
type incrementer struct {
sync.Mutex
i int
}
func (i *incrementer) Add(n int) {
i.Lock()
defer i.Unlock()
i.i += n
}
and use this type for w
, y
and z
. 并将此类型用于
w
, y
和z
。
Full example: https://play.golang.org/p/6wWUK2xnOCW 完整示例: https : //play.golang.org/p/6wWUK2xnOCW
var w int32 = 0
go func(){
// in the loop
atomic.AddInt32(&w, 1)
}()
Full example: https://play.golang.org/p/oUCGgKYC1-Y 完整示例: https : //play.golang.org/p/oUCGgKYC1-Y
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.