与像Python这样的其他语言相比,Golang中的WaitGroup是否落后一步?

时间:2016-02-29 19:59:35

标签: python go

我是golang的新手,我正在尝试goroutine,虽然它很容易同时运行,但我有点惊讶的是golang to"加入线程"使用WaitGroup

据我所知,goroutine需要引用WaitGroup对象来调用Done(),这意味着,我必须让goroutine接受WaitGroup对象,或者make { {1}}对象是goroutine的全局对象。

但在像Python这样的其他语言中,你可以调用WaitGroup,"控制"部分位于线程代码之外。

就像我说的那样,我对golang很新,我不知道为什么会这样设计,有人可以就这方面做些什么吗?

更新: 我希望这个论点不是基于' Goroutine vs Thread',在一天结束时他们都试图实现(某种程度)并发',我的问题更多的是关于控制程序流程。

4 个答案:

答案 0 :(得分:5)

  

为什么它是这样设计的

golang团队实际上已经多次解释过了 - 为什么我们不能杀死goroutines,为什么他们没有我们可以阅读的ID,为什么我们不能像线程{{1}那样明确地等待goroutine }}

有多次解释,但我只能找到this。基本上,作者不希望你依赖于线程局部性 - 锁定特定的线程/ goroutine,只为它拥有本地存储等等。当你没有任何方法可以知道你在哪个goroutine中让你被迫以一种真正的方式设计你的应用程序。您的代码由真正独立的部分组成,这些部分运行得很精确,而且他们并不关心究竟如何。您不关心哪个goroutine选择您的代码,您不关心哪个OS线程正在运行您的代码。这就是频道,精选和其他原语的用武之地。它们可以帮助您以这种方式构建应用程序。我相信它并不止于此。

答案 1 :(得分:3)

不,这只是另一件事,它做了不同的事情。它们甚至不具有可比性,因为WaitGroup本质上等待多个事物(并且可以在其生命周期中添加内容)和python线程join总是如此等等那件事。

那就是说,Go的图书馆更多的是为你提供你需要做更高级的事情的原始事物,而Python已经包含更多的电池和#34;哲学。使用Go提供的东西,你可以创建一个类似于python Thread的类型。它可能不是使用Go的最佳方式,但如果你愿意,你可以使用工具来完成它。然而,标准库并没有标准化这样的事情。

答案 2 :(得分:1)

来自hobbs和creker的答案特别优秀,但我觉得还有更多的话要说。

WaitGroup是管理多个goroutine的 方式的一个非常普遍的概念 - 它在很多情况下肯定是常用的,甚至是惯用的。你知道吗?能够调用thread.join()确实优于在等待早期启动的一堆线程/ goroutines时处理WaitGroups。

但Go的并发模型还有

Goroutines专门设计为拥有所有权或层次结构或句柄的概念。他们是独立,平等和负责结束自己的执行。结合强大的并发原语,Go的模型几乎具有无与伦比的灵活性。

因此,如果您发现自己几乎每次使用goroutine时都使用WaitGroups,那么您可能无法在建模和构建程序时利用并发 - 它&#39 ;你更有可能只是使用goroutines来并行化计算。

为了更直接地回答你的问题,与thread.join()之类的东西相比,WaitGroups相当原始,但是对于Go的并发模型,原始的低级构建块更有用。毕竟,goroutines不是线程,并且它们并不意味着使用完全相同的方式。

答案 3 :(得分:0)

  

据我所知,goroutine需要引用WaitGroup对象来调用Done(),这意味着,我必须让goroutine接受WaitGroup对象,或者让WaitGroup对象全局到goroutine。

我不同意WaitGroup与其他语言比较落后一步。我真的很喜欢它的简洁性。但是,我确实同意传递WaitGroup对象意味着并发逻辑会与您的业务逻辑混合在一起而我不喜欢它。

所以我想出了这个通用函数来解决这个问题:

// Parallelize parallelizes the function calls
func Parallelize(functions ...func()) {
    var waitGroup sync.WaitGroup
    waitGroup.Add(len(functions))

    defer waitGroup.Wait()

    for _, function := range functions {
        go func(copy func()) {
            defer waitGroup.Done()
            copy()
        }(function)
    }
}

以下是一个例子:

func1 := func() {
        for char := 'a'; char < 'a' + 3; char++ {
            fmt.Printf("%c ", char)
        }
}

func2 := func() {
        for number := 1; number < 4; number++ {
            fmt.Printf("%d ", number)
        }
}

Parallelize(func1, func2)  // a 1 b 2 c 3

如果您想使用它,可以在https://github.com/shomali11/util

找到它