sync.waitGroup 的协程每次输出不同的值
Goroutine with sync.waitGroup output different value each time
下面的代码每次执行后都会打印不同的值,但我希望这些值相同,如何在不使用 time.Sleep
的情况下更改下面的代码
package main
import (
"fmt"
"sync"
)
var total int
var wg sync.WaitGroup
// Inc increments the counter for the given key.
func inc(num int) {
total += num
wg.Done()
}
// Value returns the current value of the counter for the given key.
func getValue() int {
return total
}
func main() {
for i := 1; i <= 1000; i++ {
wg.Add(1)
go inc(i)
}
wg.Wait()
fmt.Println(getValue())
}
您每次获得不同值的原因是 total += num
中的竞争条件。
一个简单的修复方法是添加互斥锁:
var mu sync.Mutex
并在inc
中使用它:
func inc(num int) {
mu.Lock()
defer mu.Unlock()
total += num
wg.Done()
}
您有一场数据竞赛,结果未定。您必须同步对共享变量的访问:
var total int
var lock sync.Mutex
var wg sync.WaitGroup
// Inc increments the counter for the given key.
func inc(num int) {
lock.Lock()
defer lock.Unlock()
total += num
wg.Done()
}
// Value returns the current value of the counter for the given key.
func getValue() int {
lock.Lock()
defer lock.Unlock()
return total
}
或者,使用 sync/atomic
到 access/modify 变量。
已经提到您有“数据竞争”,使用 Mutex
是一个解决方案。或者你可以使用 atomic
包,它更快。
package main
import (
"fmt"
"sync"
"sync/atomic"
)
var total uint64
var wg sync.WaitGroup
func inc(num uint64) {
atomic.AddUint64(&total, 1)
wg.Done()
}
// Value returns the current value of the counter for the given key.
func getValue() uint64 {
return atomic.LoadUint64(&total)
}
func main() {
for i := uint64(1); i <= 1000; i++ {
wg.Add(1)
go inc(i)
}
wg.Wait()
fmt.Println(getValue())
}
下面的代码每次执行后都会打印不同的值,但我希望这些值相同,如何在不使用 time.Sleep
package main
import (
"fmt"
"sync"
)
var total int
var wg sync.WaitGroup
// Inc increments the counter for the given key.
func inc(num int) {
total += num
wg.Done()
}
// Value returns the current value of the counter for the given key.
func getValue() int {
return total
}
func main() {
for i := 1; i <= 1000; i++ {
wg.Add(1)
go inc(i)
}
wg.Wait()
fmt.Println(getValue())
}
您每次获得不同值的原因是 total += num
中的竞争条件。
一个简单的修复方法是添加互斥锁:
var mu sync.Mutex
并在inc
中使用它:
func inc(num int) {
mu.Lock()
defer mu.Unlock()
total += num
wg.Done()
}
您有一场数据竞赛,结果未定。您必须同步对共享变量的访问:
var total int
var lock sync.Mutex
var wg sync.WaitGroup
// Inc increments the counter for the given key.
func inc(num int) {
lock.Lock()
defer lock.Unlock()
total += num
wg.Done()
}
// Value returns the current value of the counter for the given key.
func getValue() int {
lock.Lock()
defer lock.Unlock()
return total
}
或者,使用 sync/atomic
到 access/modify 变量。
已经提到您有“数据竞争”,使用 Mutex
是一个解决方案。或者你可以使用 atomic
包,它更快。
package main
import (
"fmt"
"sync"
"sync/atomic"
)
var total uint64
var wg sync.WaitGroup
func inc(num uint64) {
atomic.AddUint64(&total, 1)
wg.Done()
}
// Value returns the current value of the counter for the given key.
func getValue() uint64 {
return atomic.LoadUint64(&total)
}
func main() {
for i := uint64(1); i <= 1000; i++ {
wg.Add(1)
go inc(i)
}
wg.Wait()
fmt.Println(getValue())
}