回答

收藏

sync.WaitGroup 的示例是否正确?

技术问答 技术问答 268 人阅读 | 0 人回复 | 2023-09-12

示例用法sync.WaitGroup是否正确?它给出了预期的结果,但我不确定wg.Add(4)和 的位置wg.Done()。一次加四个 goroutine 有意义wg.Add()吗?7 j; C2 g% t) S: G5 C
http://play.golang.org/p/ecvYHiie0P- V' Q; Q- S* E& d% v
    package mainimport  "fmt"    "sync"    "time")func dosomething(millisecs time.Duration,wg *sync.WaitGroup)    duration := millisecs * time.Millisecond    time.Sleep(duration)    fmt.Println("Function in background,duration:",duration)    wg.Done()}func main()    var wg sync.WaitGroup    wg.Add(4)    go dosomething(200,&wg)    go dosomething(400,&wg)    go dosomething(150,&wg)    go dosomething(600,&wg)    wg.Wait()    fmt.Println("Done")}/ P( M" l" B& i$ Y9 g( P# K- ?
结果(如预期):3 T  d3 x6 p7 A# _
    Function in background,duration: 150msFunction in background,duration: 200msFunction in background,duration: 400msFunction in background,duration: 600msDone& L* A8 S6 G7 o# ]- z; H! m# S
               
2 z7 _" o+ X2 T+ `0 t    解决方案:                                                                $ X( }& L# ?0 v6 f" P# N" Q
                                                                是的,这个例子是正确的。句子很重要wg.Add()以前发生过go防止竞争条件。以下也是正确的:
2 {" n9 V' Q' P7 n" p# e- z5 d6 X
    func main()      var wg sync.WaitGroup    wg.Add(1)    go dosomething(200,&wg)    wg.Add(1)    go dosomething(400,&wg)    wg.Add(1)    go dosomething(150,&wg)    wg.Add(1)    go dosomething(600,&wg)    wg.Wait()    fmt.Println("Done")}
    4 w$ B, y/ g: c% G7 \
然而,wg.Add当你知道它会被调用多少次时,一遍又一遍地调用是没有意义的。1 _  j5 u" E% x  {# X" n
Waitgroups如果计数器低于零,恐慌。计数器从零开始,每个Done()都是 a-1并且每个都Add()取决于参数。因此,为了确保计数器不低于并避免恐慌,有必要Add()进行担保来之前Done()。) q; ^) }7 ~/ Q9 O* g; e: B
在 Go 这种保证由内存模型提供。/ ~: C1 n: I8 K2 M6 z" ]2 R
内存模型指出,单个 goroutine 中的所有句子似乎都按照与编写相同的顺序执行。它们实际上可能不会按这个顺序排列,但结果就像它一样。goroutine 在go只有在调用它的句子后才。theAdd()出现在go在句子之前go 出现了句子the 之前Done(),我们知道 theAdd()出现在 the 之前Done()。' |) C+ ]" i+ E: u6 \, g  p
如果您将go把句子放在前面Add()程序可能正确运行。但是,由于不能保证,这将是一个竞争条件。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则