【问题标题】:Using multiple Goroutines on Go Tour Equivalent Binary Trees在 Go Tour 等效二叉树上使用多个 Goroutine
【发布时间】:2014-04-29 05:58:53
【问题描述】:

当尝试解决 Go Tour 中 Equivalent Binary Trees 问题的树遍历部分时,显而易见的解决方案是使用 recursion。其他解决方案(例如闭包)在general question 的回答中提供了有关如何解决问题的方法。

我最初的想法是在步行的每一步都使用一个 Goroutine。这不是更好、更 Go-onic(Pythonic 的 Go 等价物是什么?)解决方案吗?问题是我不知道如何 A)在树被走完后关闭通道,或 B)以其他方式发出树走完成的信号。较早的example 使用 2 个通道,一个用于数据,一个用于退出信号。通过第二个通道不符合问题定义,并且步行完成的根本问题仍然存在。是否有一个优雅的解决方案,每个步行步骤都有一个 Goroutine,或者递归是最好的解决方案?

func Walk(t *tree.Tree, ch chan int) {
    if t != nil {
        go Walk(t.Left, ch)
        ch <- t.Value
        go Walk(t.Right, ch)
    }
    //Done with this node, how do I know when all are done?
}

【问题讨论】:

标签: go goroutine


【解决方案1】:

对 walk 的每一步都使用 goroutine 是行不通的。完全除了不知道什么时候可以关闭通道(我不知道有什么好的解决方法),你不能保证得到你想要的订单。例如以下代码:

go fmt.Println(1)
go fmt.Println(2)
go fmt.Println(3)

根据调度程序选择运行这些 goroutine 的方式,可以打印 123、132、213、231、312 或 321 中的任何一个。这意味着您的 Walk 实现将不再以正确的顺序为您提供值。

只有当你确实想同时做一些事情时,Goroutines 才是正确的答案;鉴于通道的输出必须严格排序,因此在此问题中没有可利用的并发性。

【讨论】:

    【解决方案2】:

    您可以使用sync.WaitGroup

    func internalWalk(t *tree.Tree, wg *sync.WaitGroup, ch chan int) {
        wg.Add(1)
        if t != nil {
            go Walk(t.Left, ch)
            ch <- t.Value
            go Walk(t.Right, ch)
        }
        wg.Done()
    }
    func Walk(t *tree.Tree, ch chan int) {
        var wg sync.WaitGroup
        internalWalk(t, &wg, ch)
        wg.Wait()
        //they are all done now, do something here
    }
    

    【讨论】:

      猜你喜欢
      • 2012-08-26
      • 2012-08-21
      • 1970-01-01
      • 2015-06-10
      • 1970-01-01
      • 1970-01-01
      • 2010-12-14
      • 2014-09-24
      • 2014-03-22
      相关资源
      最近更新 更多