简体   繁体   English

不同goroutine中的频道消费顺序

[英]channel consume order in different goroutine

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")
}

My question is if done channel is consumed by goroutine not main goroutine. 我的问题是,已done通道是否由goroutine而非主要goroutine占用。 the program will be blocked. 该程序将被阻止。

But the fact is that the program never be blocked.main goroutine seem to be consumed the done channel everytime. 但是事实是程序永远不会被阻塞。main goroutine似乎每次都在done通道中被消耗掉。

Why? 为什么?

Although, I didn't found answer in docs, looks like receives value the routine which first tried to read from the channel. 虽然,我没有在文档中找到答案,但看起来像接收值的例程首先尝试从通道读取。 In our case, always main method is almost always reaching <-done (99.0%), because routines starts asynchronous and takes a while to run. 在我们的例子中,总是main方法几乎总是达到<-done (99.0%),因为例程开始异步运行并且需要一段时间才能运行。 But anyway, I would strongly suggest you do not rely on this, as this is not a guaranteed. 但是无论如何,我强烈建议您不要依赖于此,因为这不能保证。

To demonstrate it, look at the following example: 为了演示它,请看以下示例:

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)
}

Which will produce output 哪个会产生输出

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM