不同goroutine中的频道消费顺序

时间:2018-11-22 08:33:53

标签: go

package main

import (
    "fmt"
    "time"
)

func main() {
    done := make(chan bool)

    go func() {
        for {
            select {
            case <-done:
                fmt.Println("here")
            }
        }
    }()

    go func() {
        q := time.NewTimer(time.Second)
        <-q.C
        done <- true
    }()

    <-done
    fmt.Println("closing")
}

我的问题是,done通道是否被goroutine而非主goroutine占用。 该程序将被阻止。

但事实是该程序从未被阻止。主goroutine似乎每次都被done通道占用。

为什么?

1 个答案:

答案 0 :(得分:0)

虽然,我没有在文档中找到答案,但看起来像接收值的例程首先尝试从通道读取。在我们的例子中,总是使用main方法几乎总是达到<-done(99.0%),因为例程开始异步运行并且需要一段时间才能运行。但是无论如何,我强烈建议您不要依赖于此,因为这不能保证。

为演示它,请看以下示例:

package main

import (
    "fmt"
    "time"
)

func main() {
    done := make(chan bool)

    n := 5

    for i := 0; i < n; i++ {
        go func(i int) {
            fmt.Println(i, "Waiting to read")
            <-done
            fmt.Println(i, "DONE")
        }(i)
        time.Sleep(time.Second)
    }

    time.Sleep(time.Second)

    for i := 0 ; i < n; i++ {
        time.Sleep(time.Second)
        done <- true
    }

    time.Sleep(time.Second)
}

将产生输出

0 Waiting to read
1 Waiting to read
2 Waiting to read
3 Waiting to read
4 Waiting to read
0 DONE
1 DONE
2 DONE
3 DONE
4 DONE