【问题标题】:what is the proper way to use golang sync.WaitGroup使用 golang sync.WaitGroup 的正确方法是什么
【发布时间】:2016-12-06 20:28:21
【问题描述】:

正如golang doc 中提到的,同步是针对低级库例程的。

除了Once 和WaitGroup 类型之外,大多数是供以下用户使用的 低级库例程。更高级别的同步更好 通过渠道和沟通完成。

我不太理解这个说法,我使用了如下示例所示的同步。
我的目的只是让主线程等待所有其他线程完成,类似于 c++ 线程库中的.join()

问题:
1:这样使用同步合适吗?还是应该使用频道而不是同步?
2:频道和同步有什么区别?

var wg sync.WaitGroup      // declare the variable globally

func send(a string, b string){
    defer wg.Done()
    // do something
}
func main(){
    for i:=0; i<50; i++ {
         wg.Add(1)              // add delta
         go send("1111", "2222")
    }
    wg.Wait()                  // wait until wg becomes 0
}

任何建议都非常感谢!谢谢!

【问题讨论】:

  • 我不确定你在问什么,你的 send goroutine 的 sync.WaitGroupmain() 中的不同,所以没有同步进行。
  • @JimB 嘿,对于含糊的声明感到抱歉!我已经更新了。实际上,我在这里使用同步来在 c++ 线程中执行类似 .join() 的操作。从 doc 来看,channel 也可以这样做。使用同步是否合适?
  • 是的,这就是 WaitGroup 的用途;等待一组 goroutines。我不明白“使用同步的正确方法”的问题,因为这是一个完整的包,你可以在需要时使用它提供的东西。这不是使用sync.WaitGroup 的正确方法,因为main 中的wg 值与send 中的wg 值不同。
  • @JimB 感谢指出标题的问题,我已经更新了!对于wg,我将其声明为全局变量。我猜所有执行send() 的新线程都应该有相同的wg,比如main()?另外,如果使用sync.WaitGroup 的方法不正确,我应该如何处理该示例?非常感谢!
  • 您的问题完全是不同的 wg 值。这正是它在sync.WaitGroup docs 中的显示方式。

标签: multithreading go synchronization


【解决方案1】:

这个例子可以帮助你

var wg sync.WaitGroup
done := make(chan bool)

for _, element := range slice {
    wg.Add(1)
    go func(elem interface{}) {
        wg.Done()
    }(element)
}

go func() {
    wg.Wait()
    done <- true
}()

for {
    select {
    case done:
        fmt.Println("All goroutines completed")
        close(done)
        return
    case time.After(time.Minute * 2):
        fmt.Println("Timeout!")
        return
    }
}

【讨论】:

    【解决方案2】:

    我不知道这是否正确,但下面的代码可以在不使用较低级别的“同步”的情况下解决问题。

    package main
    
    func send(a string, b string, c chan bool) {
    //  println( a, b )
        c <- true;
    }
    
    func
    main() {
    
        c := make( chan bool )
    
        for i:=0; i<50; i++ {
            go send("1111", "2222", c)
        }
    
        w := 0
        for _ = range c {
            w += 1
            if w == 50 { break }
        }
    
    }
    

    【讨论】:

    • 不适合使用通道范围,AFAIK。如果任何例程尚未发送到通道怎么办 - 循环将不会运行。
    猜你喜欢
    • 2017-07-17
    • 2022-01-02
    • 1970-01-01
    • 2013-10-13
    • 1970-01-01
    • 2021-11-24
    • 2021-09-23
    • 2017-04-07
    • 2013-01-09
    相关资源
    最近更新 更多