当前位置: 首页 > 面试题库 >

示例对sync.WaitGroup正确吗?

胥玮
2023-03-14
问题内容

此示例用法sync.WaitGroup正确吗?它给出了预期的结果,但我不确定wg.Add(4)的位置wg.Done()。一次添加四个goroutine是否有意义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以防止出现种族状况。以下内容也是正确的:

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()为a
-1,每个Add()取决于参数。所以,为了保证计数器不会低于,避免恐慌,需要Add()进行 担保 来之前Done()

在Go中,这种保证由内存模型给出。

内存模型指出,单个goroutine中的所有语句似乎都按照与编写时相同的顺序执行。他们有可能实际上并不是按照这个顺序排列的,但结果似乎是这样。还可以确保goroutine直到go调用它的语句之后才运行。由于Add()发生在go语句之前,且go发生在语句之前Done(),我们知道Add()发生在语句之前Done()

如果要让该go语句位于之前Add(),则该程序可能会正确运行。但是,这将是一种竞赛条件,因为无法保证。



 类似资料:
  • 为了澄清,在这种假设情况下,给的参数是由用户控制的,可以是任意的;我对它们没有确切的控制权(我不能禁止输入)。但是,我可以编辑。

  • 简单表达式 正则表达式的最简单形式是在搜索字符串中匹配其本身的单个普通字符。例如,单字符模式,如 A,不论出现在搜索字符串中的何处,它总是匹配字母 A。下面是一些单字符正则表达式模式的示例: /a/ /7/ /M/ 可以将许多单字符组合起来以形成大的表达式。例如,以下正则表达式组合了单字符表达式:a、7 和 M。 /a7M/ 请注意,没有串联运算符。只须在一个字符后面键入另一个字符。 字符匹配

  • 有人能告诉我代码有什么问题吗?它只显示第一行和表头information.thks

  • 我正在尝试使用一个名为'jQuery.InstagramFeed'的库,它允许我在不使用访问令牌的情况下显示用户feed中的图像。所以,我一直在尝试使用它,但是,出于某种原因,它并没有向我展示任何东西。 我已经研究了几个星期了,我已经尝试了在这里的很多帖子(以及其他论坛)中提出的很多解决方案,比如下面这些: TypeError:$不是函数调用jQuery函数 “未捕获的TypeError:$不是函

  • 问题内容: 我正在尝试学习如何在PyQt Gui应用程序中使用QThreads。我有一些可以运行一段时间的东西,(通常)可以在其中更新Gui的点,但是我想将主要工作拆分为自己的线程(有时东西会卡住,最终有一个取消/重试按钮,如果Gui被冻结(因为主循环被阻塞),则该按钮显然不起作用)。 我已阅读https://mayaposch.wordpress.com/2011/11/01/how-to-re

  • 问题内容: 我想要一个JFrame,在左右两侧有一个边框,边框为黑色,宽度为withfOfJFrame / 10。 现在,我的尝试如下所示: 这会在左右两侧添加一个黑色边框,但是该边框具有固定的大小,并且在调整窗口大小时不会重新计算。大小甚至不是800(JFrame的开始宽度)的1/10。 我究竟做错了什么?还是有更好的方法来做到这一点? 问题答案: 您可以使用和适当的权重来获得所需的结果: