【问题标题】:Go Routines sometimes work, sometimes gives close channel errorGo Routines 有时有效,有时会出现关闭通道错误
【发布时间】:2017-08-15 17:55:06
【问题描述】:

我是 Go 新手,我正在尝试了解并发模式。当我运行以下代码时,有时会得到预期的结果(从 0 到 9999 的完整数字数组)。其他时候,我只会收到一条显示时间的“就是这样”的消息。有时我只是收到“在封闭频道上发送”错误。这里可能出了什么问题?

package main

import (
    "fmt"
    "time"
    "sync"
)

func JobsDispatcher(in chan int, data []int){
    for _, value := range data{
        in<-value
    }
    close(in)
}

func Worker(in chan int, out chan int, wg *sync.WaitGroup){
    wg.Add(1)
    for{
        inMsg, ok := <-in
        if !ok{
            wg.Done()
            return
        }
        out <- inMsg
    }

}

func PrintInt(out chan int){
    for {
        outMsg, ok := <-out
        if !ok{
            fmt.Println("")
            fmt.Println("That's it")
            return
        }
        fmt.Println(outMsg)
    }
}

func ParallelPrint(data []int){
    var wg sync.WaitGroup

    in := make(chan int)
    out := make(chan int)

    parallelStartTime := time.Now()

    go JobsDispatcher(in, data)

    for i:=0;i<5;i++{
        go Worker(in,out,&wg)
    }


    go func(){
        wg.Wait()
        close(out)
    }()
    PrintInt(out)

    fmt.Println(time.Since(parallelStartTime))

}

func main(){
    data := make([]int,0)
    for i:=0;i<10000;i++{
        data = append(data, i)
    }

    ParallelPrint(data)
}

【问题讨论】:

    标签: go concurrency goroutine


    【解决方案1】:

    这个很简单。这就是为什么你从不在 goroutine 中使用 WaitGroup 的 Add 的原因。总是在启动 goroutine 之前调用它。

    问题是你堆叠了一堆goroutine,然后立即调用Wait。 Go 不承诺在任何特定时间运行你的 goroutine,就像不保证 POSIX 或 Windows 线程一样。

    因此,在这种情况下,您为调度程序提供了一堆 goroutine 以供将来运行,但它决定先完成您的代码。所以它在运行 wg.Add() 之前运行了 wg.Wait()close(out)

    【讨论】:

      【解决方案2】:

      你想在它的goroutine之外调用wg.Add - 即:

      for i:=0;i<5;i++{
          wg.Add(1)    // Here, not inside Worker()
          go Worker(in,out,&wg)
      }
      

      否则,可以添加所有worker,在任何worker调用wg.Add之前点击wg.Wait,它会立即返回,然后关闭频道。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-04
        • 2014-10-11
        • 1970-01-01
        • 2021-07-29
        • 2021-09-09
        • 1970-01-01
        相关资源
        最近更新 更多