Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select on time.After results deadlock

Tags:

go

channel

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

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 "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: // This line changed
            c <- n                   // Add this line
        }

        println(<-c)
    }
}

It works well.

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

like image 922
Laurence Avatar asked Nov 25 '25 01:11

Laurence


1 Answers

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 "<-" Expression .
Channel  = Expression .

Looking at your code:

case c <- <-chan_never_used:

The Channel fraction is c, the Expression fraction is <-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.

like image 109
zerkms Avatar answered Nov 27 '25 15:11

zerkms



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!