普通网友 2014-09-16 02:38
浏览 41
已采纳

选择语句的细微差别

I read about select statements and its execution steps but I'm not fully understanding what's happening here.

I created two examples of a Fan-In function (from the Go Concurrency Patterns talk)

The first one:

select {
case value := <-g1:
    c <- value
case value := <-g2:
    c <- value
}

Prints from each channel as expected (each channel keeps its own counter):

Bob  : 0
Alice: 0
Bob  : 1
Alice: 1
Bob  : 2
Alice: 2
Alice: 3
Alice: 4
Bob  : 3
Alice: 5

The second one:

select {
case c <- <-g1:
case c <- <-g2:
}

It is randomly selecting a channel and discarding the other one's value:

Bob  : 0
Alice: 1
Alice: 2
Alice: 3
Bob  : 4
Alice: 5
Bob  : 6
Alice: 7
Alice: 8
Bob  : 9

Update: while writing this question, I thought the second select was equal to:

var v string
select {
case v = <-g1:
case v = <-g2:
    c <- v
}

But I was wrong, because this one always prints from the second channel (as expected from a switch like statement because there isn't fallthrough in select statements):

Bob  : 0
Bob  : 1
Bob  : 2
Bob  : 3
Bob  : 4
Bob  : 5
Bob  : 6
Bob  : 7
Bob  : 8
Bob  : 9

Does someone understand why my second example creates a sequence?

Thanks,

  • 写回答

2条回答 默认 最新

  • doukuanghuan7582 2014-09-16 05:38
    关注

    Your second select statement is interpreted as:

    v1 := <-g1
    v2 := <-g2
    select {
    case c <- v1:
    case c <- v2:
    }
    

    As described in the language spec, the RHS of each send operator will be evaluated up front when the statement is executed:

    Execution of a "select" statement proceeds in several steps:

    1. For all the cases in the statement, the channel operands of receive operations and the channel and right-hand-side expressions of send statements are evaluated exactly once, in source order, upon entering the "select" statement. The result is a set of channels to receive from or send to, and the corresponding values to send. Any side effects in that evaluation will occur irrespective of which (if any) communication operation is selected to proceed. Expressions on the left-hand side of a RecvStmt with a short variable declaration or assignment are not yet evaluated.
    2. If one or more of the communications can proceed, a single one that can proceed is chosen via a uniform pseudo-random selection. Otherwise, if there is a default case, that case is chosen. If there is no default case, the "select" statement blocks until at least one of the communications can proceed.
    3. ...

    So as step (1) both <-g1 and <-g2 will be evaluated, receiving values from each channel. This may block if there is nothing to receive yet.

    At (2), we wait until c is ready to send a value and then randomly choose a branch of the select statement to execute: since they are both waiting on the same channel, they are both ready to proceed.

    This explains the behaviour you saw where values are dropped and you got non-deterministic behaviour in which value was sent to c.

    If you want to wait on g1 and g2, you will need to use the first form for your statement as you've discovered.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?