Go Routines有时可以工作,有时会产生密切的通道错误

Jit*_*rew 1 concurrency go goroutine

我是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)
}
Run Code Online (Sandbox Code Playgroud)

Zan*_*ynx 5

这个很容易.这就是为什么你从不在goroutine中使用WaitGroup的Add.始终在开始goroutine之前调用它.

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

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