英文:
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
。我在这里漏掉了什么?
英文:
Given the following:
<!-- language: lang-go -->
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)
}
I would expect x
to always reach 100
by the time it prints at the end, but it sometimes prints as low as 95
. What am I missing here?
答案1
得分: 5
在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)
我建议在发现Go程序中有多个goroutine时,如果遇到令人困惑的情况,可以运行竞争检测器。
英文:
There's a race on x
. One fix is to protect x
with a mutex:
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)
I suggest running the race detector whenever one finds something puzzling in a Go program with more than one goroutine.
答案2
得分: 1
使用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)
}
使用sync.atomic的AddInt32
方法可以以原子方式增加x的值。在循环中的每个goroutine中,我们使用atomic.AddInt32
来递增x的值。通过使用原子操作,我们可以确保多个goroutine同时访问和修改x时不会发生竞争条件。最后,我们使用fmt.Println
打印出n和x的值。
英文:
use sync.atomic method to access x atomically.
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)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论