Why does this golang program hang in playground when using for loop with select?

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

Why does this golang program hang in playground when using for loop with select?

问题

考虑以下playground

messages := make(chan int, 1)
done := make(chan bool)
go func() {
    for {
        select {
        case msg := <-messages:
            fmt.Println("接收器一", msg)
        case signal := <-done:
            fmt.Println(signal)
            return
        default:
            fmt.Println("未接收到消息")
        }
    }
}()
go func() {
    for {
        select {
        case msg := <-messages:
            fmt.Println("接收器二", msg)
        case signal := <-done:
            fmt.Println(signal)
            return
        default:
            fmt.Println("未接收到消息")
        }
    }
}()
go func() {
    for i := 0; i < 2; i++ {
        messages <- i
    }
    done <- true
    done <- true
    done <- true
}()

<-done

我试图模拟从一个线程向另外两个线程进行通信,但是在playground中上述代码似乎无法正常运行。

有没有什么技巧可以使程序正常工作?

英文:

Consider this playground

    messages := make(chan int, 1)
    done := make(chan bool)
    go func() {
        for {
        select {
            case msg := &lt;- messages:
                fmt.Println(&quot;receiver one&quot;, msg)
            case signal := &lt;-done :
                fmt.Println(signal)
                return
            default:
                fmt.Println(&quot;no message received&quot;)
        } 
        }
    }()
    go func() {
        for {
        select {
            case msg := &lt;- messages:
                fmt.Println(&quot;receiver two&quot;, msg)
            case signal := &lt;-done :
                fmt.Println(signal)
                return
            default:
                fmt.Println(&quot;no message received&quot;)
        } 
        }
    }()
    go func() {
       for i := 0; i &lt; 2; i++ {
           messages&lt;-i
       }
       done&lt;-true
       done&lt;-true
       done&lt;-true
    }()

    &lt;-done

I am trying to simulate communicate from one thread to two other thread, but it seems like the above code is running fine in my local but not in playground.

Is there a trick to make the program work?

答案1

得分: 2

你应该从select语句中删除default子句。

由于你的select语句位于for循环内部,并且default子句会阻止它阻塞,所以循环必须经过很多次迭代才能接收到任何消息。

看起来Playground检测到这个问题并停止了程序。

英文:

You should remove the default clauses from the select statements.

Since your select statement is within a for loop and the default clause prevents it from blocking, the loop has to go through a lot of cycles before any message will be received.

Looks like Playground detects it and stops the program.

答案2

得分: 1

如@dev.bmax已经提到的,你错误地使用了default关键字。
请查看这篇关于使用default关键字的小文章。

另外,尝试在程序开头添加runtime.GOMAXPROCS(4),运行几次并检查输出,看看它的工作方式:

https://play.golang.org/p/TLDHNg6urB

这是一个正确的示例供你参考:

https://play.golang.org/p/bc0TGdmx1Y

请注意,在这种情况下,你应该为停止额外的和主要的goroutine使用不同的通道。

英文:

As @dev.bmax already mentioned, you use default in a wrong way.
Check this small article about using default keyword.

Also, try to add runtime.GOMAXPROCS(4) on the beginning of your program, run few times and check output to see, how it's working:

https://play.golang.org/p/TLDHNg6urB

Here's correct example for you:

https://play.golang.org/p/bc0TGdmx1Y

Note, that in this case you should use different channels for stopping additional and main goroutines.

huangapple
  • 本文由 发表于 2017年6月11日 16:04:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/44481659.html
匿名

发表评论

匿名网友

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

确定