sync.WaitGroup 的示例是否正确? [英] Example for sync.WaitGroup correct?

查看:18
本文介绍了sync.WaitGroup 的示例是否正确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个 sync.WaitGroup 的示例用法是否正确?它给出了预期的结果,但我不确定 wg.Add(4)wg.Done() 的位置.用 wg.Add() 一次添加四个 goroutine 有意义吗?

Is this example usage of sync.WaitGroup correct? It gives the expected result, but I am unsure about the wg.Add(4) and the position of wg.Done(). Does it make sense to add the four goroutines at once with wg.Add()?

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 语句之前很重要,以防止竞争条件.以下也是正确的:

Yes, this example is correct. It is important that the wg.Add() happens before the go statement to prevent race conditions. The following would also be correct:

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 是没有意义的.

However, it is rather pointless to call wg.Add over and over again when you already know how many times it will be called.

Waitgroups 会发生恐慌.计数器从零开始,每个 Done() 是一个 -1 并且每个 Add() 取决于参数.因此,为了确保计数器永远不会低于并避免恐慌,您需要 Add()保证 出现在 Done().

Waitgroups panic if the counter falls below zero. The counter starts at zero, each Done() is a -1 and each Add() depends on the parameter. So, to ensure that the counter never drops below and avoid panics, you need the Add() to be guaranteed to come before the Done().

在 Go 中,这种保证由 内存模型提供.

In Go, such guarantees are given by the memory model.

内存模型指出,单个 goroutine 中的所有语句似乎都以与编写它们相同的顺序执行.它们实际上可能不会按该顺序排列,但结果就好像它是一样的.还保证 goroutine 在调用了 go 语句之后才会运行它.由于 Add() 出现在 go 语句之前,而 go 语句出现在 Done() 之前,我们知道 Add() 发生在 Done() 之前.

The memory model states that all statements in a single goroutine appear to be executed in the same order as they are written. It is possible that they won't actually be in that order, but the outcome will be as if it was. It is also guaranteed that a goroutine doesn't run until after the go statement that calls it. Since the Add() occurs before the go statement and the go statement occurs before the Done(), we know the Add() occurs before the Done().

如果您将 go 语句放在 Add() 之前,程序可能会正确运行.然而,这将是一个竞争条件,因为它不能得到保证.

If you were to have the go statement come before the Add(), the program may operate correctly. However, it would be a race condition because it would not be guaranteed.

这篇关于sync.WaitGroup 的示例是否正确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆