sync.WaitGroup 没有像我预期的那样表现,我在这里缺少什么?
sync.WaitGroup not behaving as I expect, what am I missing here?
鉴于以下情况:
package main
import (
"fmt"
"sync"
)
func main() {
n := 100
var wg sync.WaitGroup
wg.Add(n)
x := 0
for i := 0; i < n; i++ {
go func() {
defer wg.Done()
x++
}()
}
wg.Wait()
fmt.Println(n, x)
}
我希望 x
在最后打印时总是达到 100
,但它有时会打印到 95
。我在这里错过了什么?
x
有一场比赛。一种解决方法是使用互斥体保护 x
:
var mu sync.Mutex
var wg sync.WaitGroup
wg.Add(n)
x := 0
for i := 0; i < n; i++ {
go func() {
defer wg.Done()
mu.Lock()
x++
mu.Unlock()
}()
}
wg.Wait()
fmt.Println(n, x)
我建议 运行 race detector 每当有人在一个包含多个 goroutine 的 Go 程序中发现一些令人费解的东西时。
使用sync.atomic方法以原子方式访问x。
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
n := 100
var wg sync.WaitGroup
wg.Add(n)
var x int32
for i := 0; i < n; i++ {
go func() {
defer wg.Done()
atomic.AddInt32(&x, 1)
}()
}
wg.Wait()
fmt.Println(n, x)
}
鉴于以下情况:
package main
import (
"fmt"
"sync"
)
func main() {
n := 100
var wg sync.WaitGroup
wg.Add(n)
x := 0
for i := 0; i < n; i++ {
go func() {
defer wg.Done()
x++
}()
}
wg.Wait()
fmt.Println(n, x)
}
我希望 x
在最后打印时总是达到 100
,但它有时会打印到 95
。我在这里错过了什么?
x
有一场比赛。一种解决方法是使用互斥体保护 x
:
var mu sync.Mutex
var wg sync.WaitGroup
wg.Add(n)
x := 0
for i := 0; i < n; i++ {
go func() {
defer wg.Done()
mu.Lock()
x++
mu.Unlock()
}()
}
wg.Wait()
fmt.Println(n, x)
我建议 运行 race detector 每当有人在一个包含多个 goroutine 的 Go 程序中发现一些令人费解的东西时。
使用sync.atomic方法以原子方式访问x。
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
n := 100
var wg sync.WaitGroup
wg.Add(n)
var x int32
for i := 0; i < n; i++ {
go func() {
defer wg.Done()
atomic.AddInt32(&x, 1)
}()
}
wg.Wait()
fmt.Println(n, x)
}