【问题标题】:why golang select statement does not randomly choose a case为什么golang select语句不随机选择一个case
【发布时间】:2016-07-20 01:08:01
【问题描述】:

这类似于go tutorial select statement,但我没有从那个帖子中得到答案。所以我在这里问。感谢您的回答。

http://tour.golang.org/concurrency/5 中,似乎“case c

基于语句“A select阻塞直到它的一个case可以运行,然后它执行那个case。如果多个都准备好了,它会随机选择一个。”,当“case

我还将选择块更改为如下所示。然后在前 10 次循环中,程序随机打印 1-6,但程序退出一次(第 11 次输出)退出通道的值为 0。

我的问题是,如果准备好的案例是随机选择的,那么为什么第11个选择总是退出案例。

select {
    case c <- 1:
        x, y = y, x+y
    case c <- 2:
        x, y = y, x+y
    case c <- 3:
        x, y = y, x+y
    case c <- 4:
        x, y = y, x+y
    case c <- 5:
        x, y = y, x+y
    case c <- 6:
        x, y = y, x+y
    case <-quit:
        fmt.Println("quit")
        return
    }

【问题讨论】:

  • 但是c &lt;- xquit 的示例中准备就绪(基于您链接到的示例)。您是否使用与游览相同的代码?
  • @JimB 我只知道 c 通道是无缓冲的。谢谢!

标签: select go goroutine


【解决方案1】:

在 case 语句中,您将值发送到 c(例如 c &lt;- 1),该值会阻塞,直到将 c 读取为 foo := &lt;- c。当有东西写入quit 时,它会遇到&lt;-quit 所在并退出选择的情况。

从这个例子

package main

import (
    "fmt"
    "time"
)

func main() {
    c := make(chan int)
    quit := make(chan struct{})

    go func(q chan<- struct{}) {
        time.Sleep(5 * time.Second)
        q <- struct{}{}
    }(quit)

    go func(ch chan<- int) {
        var x int
        for range time.Tick(1 * time.Second) {
            c <- x
            x++
        }
    }(c)

    for {
        select {
        case foo := <-c:
            fmt.Println("Foo", foo)
        case bar := <-c:
            fmt.Println("Bar", bar)
        case <-quit:
            fmt.Println("quit")
            return
        }
    }
}

您可以在机器上看到随机打印的值:

$ go run foo.go
Bar 0
Bar 1
Foo 2
Bar 3
quit

$ go run foo.go
Bar 0
Foo 1
Bar 2
Bar 3
quit

【讨论】:

  • 谢谢。你的第一句话应该是原因。但是这个例子似乎不是原因。我将您的代码更改为 go func(ch chan&lt;- int) { var x int for { c &lt;- x x++ } }(c)for range time.Tick(1 * time.Second){ select { 您可以看到 c go func(q chan<- int) { time.Sleep(2 * time.Second) q <- 0 }(quit) 并尝试打印
  • 我不确定我是否理解您的意思,介意用您正在谈论的代码更新您的问题吗? c &lt;- x 将阻塞任何地方,而不仅仅是在选择中,除非从 c 读取某些内容,因为 c 是一个无缓冲通道 play.golang.org/p/3BemJwJjTk
  • 另外值得注意的是,如果您在 go playground 上尝试这个,您不会看到太多随机性,因为 Playground 本身是确定性的。
  • Ahhhh,我刚刚知道 c 通道是无缓冲的。谢谢!
猜你喜欢
  • 2021-02-05
  • 1970-01-01
  • 2020-01-18
  • 2022-11-11
  • 1970-01-01
  • 2014-09-16
  • 2013-03-23
  • 2023-04-07
  • 1970-01-01
相关资源
最近更新 更多