回答

收藏

sync.WaitGroup 的示例是否正确?

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

示例用法sync.WaitGroup是否正确?它给出了预期的结果,但我不确定wg.Add(4)和 的位置wg.Done()。一次加四个 goroutine 有意义wg.Add()吗?5 P" m9 M/ m' t
http://play.golang.org/p/ecvYHiie0P
# p( ]$ c0 H* F9 b  J
    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")}
    * E$ j4 |9 P6 Q; U
结果(如预期):
; z7 H  r( a4 e* N
    Function in background,duration: 150msFunction in background,duration: 200msFunction in background,duration: 400msFunction in background,duration: 600msDone6 X: H* G0 ?% k8 Z9 _% _
               7 i7 k. g+ m& J! V0 L) [# N  S/ i
    解决方案:                                                               
# D  Y; p( n7 R$ y5 z$ o/ ?                                                                是的,这个例子是正确的。句子很重要wg.Add()以前发生过go防止竞争条件。以下也是正确的:
) q+ o# p3 {! y% l) K
    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")}
    1 ?9 j" C. n6 l
然而,wg.Add当你知道它会被调用多少次时,一遍又一遍地调用是没有意义的。
. ?) v# m0 F/ T4 U5 B$ q7 B- }Waitgroups如果计数器低于零,恐慌。计数器从零开始,每个Done()都是 a-1并且每个都Add()取决于参数。因此,为了确保计数器不低于并避免恐慌,有必要Add()进行担保来之前Done()。
9 \$ C# u- I9 t7 M5 ]5 [" h  |在 Go 这种保证由内存模型提供。) V: u+ r! [7 r! D! Z
内存模型指出,单个 goroutine 中的所有句子似乎都按照与编写相同的顺序执行。它们实际上可能不会按这个顺序排列,但结果就像它一样。goroutine 在go只有在调用它的句子后才。theAdd()出现在go在句子之前go 出现了句子the 之前Done(),我们知道 theAdd()出现在 the 之前Done()。
4 r; O. w& K( M4 y) |如果您将go把句子放在前面Add()程序可能正确运行。但是,由于不能保证,这将是一个竞争条件。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则