选择按时进行。在结果死锁之后。

huangapple go评论93阅读模式
英文:

Select on time.After results deadlock

问题

以下是翻译的内容:

package main

import "time"

func main() {
    chan_never_used := make(chan int, 10)

    c := make(chan int, 10)
    for {
        select {
        case <-time.After(time.Second):
            c <- 0
        case c <- <-chan_never_used:
        }

        println(<-c)
    }
}

上面的代码会导致 fatal error: all goroutines are asleep - deadlock!

但是如果我改变一行代码:

package main

import "time"

func main() {
    chan_never_used := make(chan int, 10)

    c := make(chan int, 10)
    for {
        select {
        case <-time.After(time.Second):
            c <- 0
        case n := <-chan_never_used: // 这行代码改变了
            c <- n                   // 添加了这行代码
        }

        println(<-c)
    }
}

它可以正常工作。

为什么第一个版本的代码会导致死锁,而这个改变可以使代码正常工作?

英文:
package main

import &quot;time&quot;

func main() {
    chan_never_used := make(chan int, 10)

    c := make(chan int, 10)
    for {
        select {
        case &lt;-time.After(time.Second):
            c &lt;- 0
        case c &lt;- &lt;-chan_never_used:
        }

        println(&lt;-c)
    }
}

https://play.golang.org/p/7hZMdITecg

The code above results in fatal error: all goroutines are asleep - deadlock!.

But if I change one line:

package main

import &quot;time&quot;

func main() {
    chan_never_used := make(chan int, 10)

    c := make(chan int, 10)
    for {
        select {
        case &lt;-time.After(time.Second):
            c &lt;- 0
        case n := &lt;-chan_never_used: // This line changed
            c &lt;- n                   // Add this line
        }

        println(&lt;-c)
    }
}

It works well.

Why the first version of code results in deadlock and why could this change make the code work?

答案1

得分: 2

根据标准,select语句由一系列的Send语句Receive语句组成。

在这种情况下,是send语句。

send语句的定义如下:

SendStmt = Channel "<-" Expression .
Channel  = Expression .

看看你的代码:

case c <- <-chan_never_used:

Channel 部分是 cExpression 部分是 <-chan_never_used

因此,send语句的select语义(可能)不适用,因为是表达式造成了阻塞。在应用Send语句的语义之前,必须完全评估Expression部分。

英文:

As per the standard the select statement contains of a bunch of Send or Receive statements.

In this case it is the send statement.

Send statement is defined as:

SendStmt = Channel &quot;&lt;-&quot; Expression .
Channel  = Expression .

Looking at your code:

case c &lt;- &lt;-chan_never_used:

The Channel fraction is c, the Expression fraction is &lt;-chan_never_used.

So, the select semantics of the Send Statement of being (potentially) non-blocking is not applicable because it is the expression that blocks. And before the Send Statements semantics is applied the Expression part must be completely evaluated.

huangapple
  • 本文由 发表于 2017年4月9日 13:34:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/43303406.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定