Reputation: 97
Given the following:
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?
Upvotes: 1
Views: 147
Reputation: 151
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)
}
Upvotes: 1
Reputation: 120941
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.
Upvotes: 5