sync.WaitGroup的行为不符合我的预期,我在这里缺少什么?

时间:2015-09-26 23:22:13

标签: go goroutine

鉴于以下内容:

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一样低。我在这里缺少什么?

2 个答案:

答案 0 :(得分:6)

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)

playground example

我建议只要在Go程序中发现有多个goroutine的东西就会运行race detector

答案 1 :(得分: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)
}