Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A simple example about Go Channel with deadlock and why

My code as follows:

package main

import (
    "fmt"
)

func main() {
    c1 := make(chan int)
    fmt.Println("push c1: ")
    c1 <- 10
    g1 := <- c1
    fmt.Println("get g1: ", g1)
}

when I debug with delve, it prints this result:

push c1:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
        D:/Go/projects/hello-world/src/ch9/code9_6/code1.go:10 +0xde
Process 6276 has exited with status 2

I don't know why, it's just one simple channel example, I make one channel, send value to it and get value from it, just this, someone can tell me why, and how to correct it, Thx a lot.

like image 304
Sunshine Avatar asked Jan 12 '19 08:01

Sunshine


2 Answers

Quote from https://tour.golang.org/concurrency/2:

By default, sends and receives block until the other side is ready. This allows goroutines to synchronize without explicit locks or condition variables.

Channels are meant to work between goroutines, but you have only 1. So c1 <- 10 blocks execution, until someone (usually in other goroutine) receives the value.

To fix that:

package main

import (
    "fmt"
)

func main() {
    c1 := make(chan int)

    go func() {
        g1 := <- c1 // wait for value
        fmt.Println("get g1: ", g1)
    }()

    fmt.Println("push c1: ")
    c1 <- 10 // send value and wait until it is received.
}

Try executing it in The Go Playground.

I suggest you go through official Go concurrency tour starting from https://tour.golang.org/concurrency/1

EDIT: Another option is to use Buffered channel, like below. However making Buffered channel does not mean it has non-blocking send/receive operations. It just means it will block send after N values in queue, where N is always predefined number. Internally it will store sent values into an array, and block until values are received (like non-buffered channel) when that array is filled.

package main

import (
    "fmt"
)

func main() {
    c1 := make(chan int, 1) // buffers 1 value without blocking.
    fmt.Println("push c1: ")
    c1 <- 10
    g1 := <- c1
    fmt.Println("get g1: ", g1)
}

Try it on Go Playground.

like image 133
metalim Avatar answered Oct 14 '22 14:10

metalim


Channel could be buffered or nonbuffered (it means that it's possible to send into it the only value of a variable) and when you try to read from a nonbuffered channel you lock a goroutine in which you try to execute this operation. In order to unlock it, you have to write into the channel in another goroutine and vice versa, that is when you write on a channel you lock a goroutine in which you execute this operation but it will be unlocked when you try to read from the channel in another goroutine. You should learn this feature for developing flexible (with concurrency) programs. Channels are used for sending data between different routines which have to work independently or in parallel. You can create a pipeline of two, three or more goroutines for sending data from one goroutine to another by sequentially.

In this example I create a channel of bool type ch. It's impossible to say exactly what line of 9-th and 11-th will be executed the first. sendq - is a list goroutines that are waiting writing to the channel. In this case the main (func main) routine is waiting when a line number 9 will be executed.

enter image description here

Another example where we have deadlock. Execution will never go to 8-th line so goroutine (next line), in which I try to write data to channel, will never be launched.

enter image description here

More information about channels you can find here: http://dmitryvorobev.blogspot.com/2016/08/golang-channels-implementation.html

There is such term as m:n scheduling. Golang has a m:n scheduler that is at m goroutines could be scheduled on n OS threads by Go scheduler. https://medium.com/@riteeksrivastava/a-complete-journey-with-goroutines-8472630c7f5c

I recommend you to look through this book: https://www.amazon.com/Programming-Language-Addison-Wesley-Professional-Computing/dp/0134190440 . In my opinion, this is the best book about Golang that gives a description of lots of conceptions and features of this language.

About the difference between concurrency and parallelism you can read here: https://www.ardanlabs.com/blog/2018/12/scheduling-in-go-part3.html

like image 36
echmel Avatar answered Oct 14 '22 14:10

echmel