示例用法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()程序可能正确运行。但是,由于不能保证,这将是一个竞争条件。