这个例子的用法是sync.WaitGroup
正确的?它给出了预期的结果,但我不确定wg.Add(4)
和位置wg.Done()
。一次添加四个 goroutine 是否有意义wg.Add()
?
http://play.golang.org/p/ecvYHiie0P http://play.golang.org/p/ecvYHiie0P
package main
import (
"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")
}
结果(如预期):
Function in background, duration: 150ms
Function in background, duration: 200ms
Function in background, duration: 400ms
Function in background, duration: 600ms
Done
是的,这个例子是正确的。重要的是wg.Add()
发生在go
声明以防止竞争条件。以下也将是正确的:
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")
}
然而,打电话是毫无意义的wg.Add
当你已经知道它会被调用多少次时,就会一遍又一遍地重复。
Waitgroups
如果计数器降到零以下,就会出现恐慌。计数器从零开始,每次Done()
is a -1
和每个Add()
取决于参数。因此,为了确保计数器永远不会低于并避免恐慌,您需要Add()
to be 保证来之前Done()
.
在 Go 中,这样的保证是由记忆模型 http://golang.org/ref/mem.
内存模型指出,单个 goroutine 中的所有语句似乎都按照写入的顺序执行。它们实际上可能不会按这个顺序排列,但结果就像是这样。还保证了goroutine 直到之后才会运行go调用它的声明 http://golang.org/ref/mem#tmp_4。自从Add()
发生在go
声明和go
语句发生在Done()
,我们知道Add()
发生在Done()
.
如果你有go
声明出现在Add()
,程序可以正确运行。然而,这将是一个竞争条件,因为它无法得到保证。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)