Why is the following program deadlock? - go

package main
import "fmt"
func main() {
c := make(chan int)
c <- 5
a := <- c
fmt.Println(a)
}
Here both the data is being sent and recieved to/from the channel but still the error is being displayed:
fatal error: all goroutines are asleep - deadlock!

The channel is unbuffered. So if one writes to it - and no other goroutine is reading from it - it is a guaranteed deadlock.
To fix, either make it unbuffered:
c := make(chan int, 1)
or write asynchronously from another goroutine:
go func() {
c <- 5
}()
https://play.golang.org/p/RRJILbuZKTQ
Since channels are used to communicate between goroutines, its extremely rare one writes to a channel from the same goroutine as the reads. An exception may be, if using a channel as a resource pool and one wants to pre-populate the (buffered) channel.

Your channel c doesn't have any buffer (even a single cell), which means that the main goroutine locks at the c <- 5 line. Since it is the only goroutine in your application, it creates a deadlock.

Channels make(chan int) has implicit size zero ( ref: https://golang.org/ref/spec#Making_slices_maps_and_channels)
A channel of size zero is unbuffered. A channel of specified size make(chan int, n) is buffered. See http://golang.org/ref/spec#Send_statements for a discussion on buffered vs. unbuffered channels. The example at http://play.golang.org/p/VZAiN1V8-P illustrates the difference.
Here, channel <-c or c <- will be blocked until someone processes it (concurrently). So, change c := make(chan int) to c := make(chan int,1)
package main
import "fmt"
func main() {
c := make(chan int, 1)
c <- 5
a := <- c
fmt.Println(a)
}

Related

Update the capacity of golang buffered channel at runtime

I am working on a piece of code wherein the capacity of the buffered channel should be a tunable parameter .i.e. after 1st time initialization of the buffered channel, I want to change the capacity of channel if required so.
package main
import (
"fmt"
)
func main() {
ch := make(chan int, 2)
ch <- 1
ch <- 2
fmt.Println(<-ch)
ch = make(chan int, 4)
ch <- 3
ch <- 4
fmt.Println(<-ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
}
The above fails with error fatal error: all goroutines are asleep - deadlock! after printing 1,3 and 4.
The following code works where all the value in the channel is read before updating its capacity.
package main
import (
"fmt"
)
func main() {
ch := make(chan int, 2)
ch <- 1
ch <- 2
fmt.Println(<-ch)
fmt.Println(<-ch)
ch = make(chan int, 4)
ch <- 3
ch <- 4
fmt.Println(<-ch)
fmt.Println(<-ch)
}
Could someone help here whether updating the buffered channel capacity is possible at runtime while it still holds some value that are yet to read.
Could someone help here whether updating the buffered channel capacity is possible at runtime while it still holds some value that are yet to read.
This is impossible. Once constructed via make a channel keeps it capacity which is unchangeable at runtime.

Problem Understanding Golang Concurrency Code

I just started learning golang, while I was going through concurrency I accidentally wrote this code:
import (
"fmt"
)
func squares(c chan int) {
for i := 0; i < 4; i++ {
num := <- c
fmt.Println(num * num)
}
}
func main() {
fmt.Println("main start")
c := make(chan int)
go squares(c)
c <- 1
c <- 2
c <- 3
c <- 4
go squares(c)
c <- 5
c <- 6
c <- 7
c <- 8
fmt.Println("main stop")
}
Originally I was suppose to assign c := make(chan int, 3).
I am having trouble understanding the output of the code I've written.
main start
1
4
9
25
36
49
16
main stop
I would like to understand how the code is executed.
I was expecting error: all goroutines are asleep - deadlock!
Many thanks!
I am not sure to really understand what you wanted to achieve, especially the reason of that weird loop :
for i := 0; i < 4; i++ {
num := <- c
fmt.Println(num * num)
}
But anyway.
First have all, some explanations on how works channels and goroutines.
A Channel is a thread safe messaging pipe used to share data accross differents executions contexts. A channel is creating with make instruction, then
c := make(chan int, 3)
means create a channel of int type with a "buffer" size of 3. This element is very important to understand. Channel do follow a producer / consumer pattern with that bases rules :
For producer :
if I try to push some data in a channel with some "free space", it doesn't block and next instructions are executed
If I try to push some data in a channel without "free space", it blocks till previous has been treated
For consumer :
If I try to take element from an empty channel, it block untill some data come
If I try to take element from a non empty channel, it take the first (Channel is a FIFO)
Please note that all blocking operations may be turned non-blocking using some special pattern available through select instruction, but that's another subject :).
Goroutine are light sub-processes, routines (No thread). It is no place here to explain all in details, but what is important is 1 goroutine === 1 execution stack.
So in your case, the output is quite predictable till there is only one consumer. Once you start the second Goroutine, the consumption order is still predictable (the size of the channel is only one), but the execution order not !
One thing is noticable: you have only 7 output... That because your main goroutine ends before it happends, terminating the whole program execution. That point explain why you didn't have the all goroutines are asleep - deadlock!.
If you want to have that, you just should add <- c somewhere at the end of the main :
package main
import (
"fmt"
)
func squares(c chan int) {
for i := 0; i < 4; i++ {
num := <-c
fmt.Println(num * num)
}
}
func main() {
fmt.Println("main start")
c := make(chan int)
go squares(c)
c <- 1
c <- 2
c <- 3
c <- 4
go squares(c)
c <- 5
c <- 6
c <- 7
c <- 8
<-c
fmt.Println("main stop")
}
You will have the behavior I think you expect :
main start
1
4
9
25
36
49
64
16
fatal error: all goroutines are asleep - deadlock!
Edit : on step by step, execution :
// a goroutine is created and c is empty. because
// the code of `squares` act as a consumer, the goroutine
// "block" at instruction `num := <-c`, but not the main goroutine
go squares(c)
// 1 is pushed to the channel. Till "c" is not full the main goroutine
// doesn't block but the other goroutine may be "released"
c <- 1
// if goroutine of squares has not consume 1 yet, main goroutine block
// untill so, but is released just after
c <- 2
// it continues with same logic
c <- 3
c <- 4
// till main goroutine encountered `<- c` (instruction I added) .
// Here, it behave as a consumer of "c". At this point all
// goroutine are waiting as consuler on "c" => deadlock

Write to channel blocked forever

I am stuck in a strange situation where the write operation to the channel never happens.
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int)
s := make(chan bool)
k := make(chan bool)
fmt.Println("start")
go func() {
fmt.Println("routine 1")
s <- true
}()
go func() {
fmt.Println("routine 2")
for {
select {
case <-s :
for i := 0; i < 3; i++ {
fmt.Println("before")
c <- i
fmt.Println("after")
}
case <- k :
fmt.Println("k ready")
break
}
}
}()
go func() {
fmt.Println("routine 3")
for {
select {
case x := <- c :
fmt.Println("x=", x)
k <- true
fmt.Println("k done")
}
}
}()
time.Sleep(1000 * time.Millisecond)
}
And here is the output:
start
routine 1
routine 2
before
routine 3
x= 0
after
before
I wonder why the write to the channel k blocks, but the log statement fmt.Println("k ready") is never printed.
Here is what I think :
go routine 1 writes true to channel s
go routine 2 writes 0 to
channel c and waits because buffer size is 0, it will not be able to
write '1' to it unless someone reads channel c
go routine 3 comes into the picture, reads channel c (now go routine 2
can write to c once go routine 2 resumes) prints the value of x. NOW IT SHOULD BE ABLE TO WRITE TO CHANNEL K but that is not happening
According to me it should be able to write to channel k then case 2 of goroutine should execute and print "k ready"
Can anyone explain me why write to the channel blocked?
As a fix I know I can increase the buffer size of channel c and everything will get printed but I am not interested in fixing this, instead I want to understand this scenario.
A nice blog to understand the above case.
You have a deadlock.
goroutine 1 writes to s then quits
goroutine 2 reads from s, and writes to c
goroutine 3 reads from c, and writes to k, and this blocks because nothing is reading from k, because goroutine 2 is blocked in the write to k above.
goroutine 2 writes to c again which blocks as goroutine 3 is still trying to write to k and thus is not reading from c
Contrary to what you say, you don't have a buffer size of 1. You have a buffer size of zero (i.e. an unbuffered channel), so a write will block until something reads. This is probably the source of your misunderstanding. Per the language specification:
A new, initialized channel value can be made using the built-in function make, which takes the channel type and an optional capacity as arguments:
make(chan int, 100)
The capacity, in number of elements, sets the size of the buffer in the channel. If the capacity is zero or absent, the channel is unbuffered and communication succeeds only when both a sender and receiver are ready. Otherwise, the channel is buffered and communication succeeds without blocking if the buffer is not full (sends) or not empty (receives). A nil channel is never ready for communication.

Goroutines channels and "stopping short"

I'm reading/working through Go Concurrency Patterns: Pipelines and cancellation, but i'm having trouble understanding the Stopping short section. We have the following functions:
func sq(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for n := range in {
out <- n * n
}
close(out)
}()
return out
}
func gen(nums ...int) <-chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
close(out)
}()
return out
}
func merge(cs ...<-chan int) <-chan int {
var wg sync.WaitGroup
out := make(chan int, 1) // enough space for the unread inputs
// Start an output goroutine for each input channel in cs. output
// copies values from c to out until c is closed, then calls wg.Done.
output := func(c <-chan int) {
for n := range c {
out <- n
}
wg.Done()
}
wg.Add(len(cs))
for _, c := range cs {
go output(c)
}
// Start a goroutine to close out once all the output goroutines are
// done. This must start after the wg.Add call.
go func() {
wg.Wait()
close(out)
}()
return out
}
func main() {
in := gen(2, 3)
// Distribute the sq work across two goroutines that both read from in.
c1 := sq(in)
c2 := sq(in)
// Consume the first value from output.
out := merge(c1, c2)
fmt.Println(<-out) // 4 or 9
return
// Apparently if we had not set the merge out buffer size to 1
// then we would have a hanging go routine.
}
Now, if you notice line 2 in merge, it says we make the out chan with buffer size 1, because this is enough space for the unread inputs. However, I'm almost positive that we should allocate a chan with buffer size 2. In accordance with this code sample:
c := make(chan int, 2) // buffer size 2
c <- 1 // succeeds immediately
c <- 2 // succeeds immediately
c <- 3 // blocks until another goroutine does <-c and receives 1
Because this section implies that a chan of buffer size 3 would not block. Can anyone please clarify/assist my understanding?
The program sends two values to the channel out and reads one value from the channel out. One of the values is not received.
If the channel is unbuffered (capacity 0), then one of the sending goroutines will block until the program exits. This is a leak.
If the channel is created with a capacity of 1, then both goroutines can send to the channel and exit. The first value sent to the channel is received by main. The second value remains in the channel.
If the main function does not receive a value from the channel out, then a channel of capacity 2 is required to prevent the goroutines from blocking indefinitely.

Go channels and deadlock

I'm trying to understand the Go language. I tried to create two goroutines
that chain the flow between them using two channels:
func main() {
c1 := make(chan int)
c2 := make(chan int)
go func() {
for i := range c1{
println("G1 got", i)
c2 <- i
}
}()
go func() {
for i := range c2 {
println("G2 got", i)
c1 <- i
}
}()
c1 <- 1
time.Sleep(1000000000 * 50)
}
As expected this code prints:
G1 got 1
G2 got 1
G1 got 1
G2 got 1
....
Until the main function exits.
But if I send another value to one of the channels from main, it suddenly blocks:
func main() {
c1 := make(chan int)
c2 := make(chan int)
go func() {
for i := range c1{
println("G1 got", i)
c2 <- i
}
}()
go func() {
for i := range c2 {
println("G2 got", i)
c1 <- i
}
}()
c1 <- 1
time.Sleep(1000000000 * 1)
c1 <- 2
time.Sleep(1000000000 * 50)
}
It outputs
G1 got 1
G2 got 1
G1 got 1
G2 got 1
G1 got 2
and then blocks until the main ends.
The value "2" sent to c1 arrives to the first goroutie, which sends it to c2, but the second
goroutine never receives.
(Using buffered channels with size 1 (either c1 or c2) works in this example)
Why does it happen? When this happens in real code, how can I debug it?
nmichaels is right on with his answer, but I thought I'd add that there are ways to figure out where you're deadlocking when debugging a problem like this.
A simple one is if you're on a Unix-like OS, run the command
kill -6 [pid]
This will kill the program and give a stack trace for each goroutine.
A slightly more involved way is to attach gdb.
gdb [executable name] [pid]
You can examine the stack and variables of the active goroutine as normal, but there's no easy way to switch goroutines that I know of. You can switch OS threads in the usual way, but that might not be enough to help.
Go channels created with make(chan int) are not buffered. If you want a buffered channel (that won't necessarily block), make it with make(chan int, 2) where 2 is the size of the channel.
The thing about unbuffered channels is that they are also synchronous, so they always block on write as well as read.
The reason it deadlocks is that your first goroutine is waiting for its c2 <- i to finish while the second one is waiting for c1 <- i to finish, because there was an extra thing in c1. The best way I've found to debug this sort of thing when it happens in real code is to look at what goroutines are blocked and think hard.
You can also sidestep the problem by only using synchronous channels if they're really needed.
to prevent the channel from overflowing, you can ask for the channel's current capacity and dry it before writing again.
in my case, the game takes place at 60fps and the mouse moves much faster, so it is always good to check that the channel has been cleared before writing again.
notice that the previous data is lost
package main
import (
"fmt"
)
func main() {
// you must specify the size of the channel,
// even for just one element, or the code doesn't work
ch := make( chan int, 1 )
fmt.Printf("len: %v\n", len(ch))
fmt.Printf("cap: %v\n\n", cap(ch))
ch <- 1
for i := 0; i != 100; i += 1 {
fmt.Printf("len: %v\n", len(ch))
fmt.Printf("cap: %v\n\n", cap(ch))
if cap( ch ) == 1 {
<- ch
}
ch <- i
fmt.Printf("len: %v\n", len(ch))
fmt.Printf("cap: %v\n\n", cap(ch))
}
fmt.Printf("end!\n")
}

Resources