sync.WaitGroup示例正确吗? [英] Example for sync.WaitGroup correct?

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

问题描述

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



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在后台,持续时间:,持续时间)
wg.Done()
}

func main(){
var wg sync.WaitGroup
wg添加(4)
去dosomething(200,& wg)
去dosomething(400,& wg)
去dosomething(150,& wg)
去dosomething (600,& wg)

wg.Wait()
fmt.Println(完成)
}
pre>

结果(如预期):

 持续时间:150ms 
在后台运行,持续时间:2 00ms
后台功能,持续时间:400ms
后台功能,持续时间:600ms
完成


解决方案

是的,这个例子是正确的。 wg.Add()转到语句之前发生以防止竞争条件是很重要的。以下内容也是正确的:

  func main(){
var wg sync.WaitGroup
wg .Add(1)
go dosomething(200,& wg)
wg.Add(1)
go dosomething(400,& wg)
wg.Add(1 )
去dosomething(150,& wg)
wg.Add(1)
去dosomething(600,& wg)

wg.Wait()
fmt.Println(完成)
}

然而,它是当你已经知道它会被调用多少次时,反复地再次调用 wg.Add






等待组恐慌,如果计数器低于零。计数器从零开始,每个 Done()是一个 -1 并且每个 Add( )取决于参数。因此,您需要 Add()保证在 Done()避免恐慌。



在Go中,这样的保证是由内存模型

内存模型指出,单个goroutine中的所有语句似乎都按照写入的顺序执行。他们可能不会按照这个顺序,但结果就好像是这样。这还保证,直到转到语句之后, goroutine才会运行称之为。由于 Add()发生在 go 语句之前,而 go 语句出现在 Done()之前,我们知道 Add()出现在完成()



如果你有 go Add(),程序可能正常运行。但是,这将是一个竞争条件,因为它不会得到保证。

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")
}

Result (as expected):

Function in background, duration: 150ms
Function in background, duration: 200ms
Function in background, duration: 400ms
Function in background, duration: 600ms
Done

解决方案

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")
}

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 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, you need the Add() to be guaranteed to come before the Done() to avoid panics.

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

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().

If you were 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天全站免登陆