accurate respondetur
accurate respondetur

Reputation: 702

Buffered/Unbuffered channel

Could someone explain, why if the channel is buffered the program doesn't exit with a fatal_error?

Unbuffered channel

package main

func main() {
    c := make(chan int)
    c <- 3
}

fatal error: all goroutines are asleep - deadlock!

Buffered channel

package main

func main() {
    c := make(chan int, 1)
    c <- 3
}

[no output]

Program exited.

Thank you!

Upvotes: 8

Views: 5225

Answers (3)

beatngu13
beatngu13

Reputation: 9363

It's a core concept of Go's channels (or other CSP implementations such as Clojure's core.async library) that they are blocking. In general, as you already mentioned, there're two types of channels:

  • buffered which block if the buffer is full.
  • unbuffered which block if there's no "rendezvous", i.e. there must be someone who puts (c <-) to and someone who takes (<- c) from the channel.

In your particular case the Go runtime is smart enough to detect that there's no one who will ever take 3 from channel c. Hence, it's a deadlock and (thankfully) an error is thrown.

What you typically do when you're working with channels is using goroutines (checkout this introduction) which spawn a lightweight thread—managed by the Go runtime—to execute the body concurrently:

c := make(chan int)

go func() { c <- 3 }() // Create a new gorountine that puts 3 to the channel

fmt.Println(<- c) // Take 3 from the channel and print it in the main thread

Upvotes: 4

accurate respondetur
accurate respondetur

Reputation: 702

Thanks @Matt

I found the answer in this post How does make(chan bool) behave differently from make(chan bool, 1)? :

Actually that's the reason why your problem is generated. Un-buffered channels are only writable when there's someone blocking to read from it, which means you shall have some coroutines to work with -- instead of this single one.

Upvotes: 2

Sean
Sean

Reputation: 1803

Writing to a buffered channel doesn't block if there is room in the buffer.

If you try to put two items in the channel with a buffer size of one, you get the same error:

package main

func main() {
    c := make(chan int, 1)
    c <- 3
    c <- 4
}

gives you:

fatal error: all goroutines are asleep - deadlock!

Upvotes: 11

Related Questions