[go-nuts] Channel deadlock

158 views
Skip to first unread message

ceving

unread,
Apr 20, 2010, 7:09:02 AM4/20/10
to golang-nuts
I have the following program with three channels implementing a
logical and:

package main
import "fmt"
func main () {
a := make (chan bool)
b := make (chan bool)
c := make (chan bool)
c <- (<-a && <-b)
a <- true
b <- false
fmt.Println (<-c);
}

When I start the program I get a dead lock error:

throw: all goroutines are asleep - deadlock!

I do not understand why there is a deadlock if every channel gets read
and written. Can anybody explain?


--
Subscription settings: http://groups.google.com/group/golang-nuts/subscribe?hl=en

ceving

unread,
Apr 20, 2010, 7:23:30 AM4/20/10
to golang-nuts
On 20 Apr., 13:09, ceving <cev...@googlemail.com> wrote:
>
> Can anybody explain?

Sorry found it myself. I had to make the channel buffered and had do
switch the order of operations:

func main () {
a := make (chan bool, 1)
b := make (chan bool, 1)
c := make (chan bool, 1)
a <- true
b <- false
c <- (<-a && <-b)
fmt.Println (<-c)

Steven

unread,
Apr 20, 2010, 3:54:40 PM4/20/10
to ceving, golang-nuts
On Tue, Apr 20, 2010 at 7:23 AM, ceving <cev...@googlemail.com> wrote:
On 20 Apr., 13:09, ceving <cev...@googlemail.com> wrote:
>
> Can anybody explain?

Sorry found it myself. I had to make the channel buffered and had do
switch the order of operations:

func main () {
   a := make (chan bool, 1)
   b := make (chan bool, 1)
   c := make (chan bool, 1)
   a <- true
   b <- false
   c <- (<-a  && <-b)
   fmt.Println (<-c)
}

Yeah, the reason is that 'c <- (<-a && <-b)'  waits for another goroutine to send a value through a and b, which never happens because there's only one goroutine, so the code never makes it to 'a <- true; b <- false'. Buffering is one way to get around this, though it sort of defeats the purpose of using channels to use buffering sequentially like this.

Another way to fix this would be to do:

package main
import "fmt"
func main () {

   a := make (chan bool)
   b := make (chan bool)
   c := make (chan bool)
   go func() { c <- (<-a  && <-b)  }()

   a <- true
   b <- false
   fmt.Println (<-c);
}
 
Here, every time the main goroutine gets stuck (at 'a <- true', 'b <- false', and '<-c'), flow gets passed to the func goroutine, which then goes until it gets stuck and passes the flow back to the main goroutine. This isn't really concurrent, since only one goroutine is going at a time. The compiler isn't smart about sequential code that looks concurrent yet. I think this demonstrates the use of channels a little better, since the purpose is to allow communication between goroutines.

andrey mirtchovski

unread,
Apr 20, 2010, 4:16:02 PM4/20/10
to golang-nuts
one of the things i like most about channels is that they're
deterministic. you can easily building a very large acyclic graph of
channel-connected goroutines and be guaranteed that it will always
execute in the same order even if more than one token is being passed
around on the graph asynchronously. however, you do need a guarantee
that <-c blocks unless there's data on it for that to work, which is
the snag you hit.

ceving

unread,
Apr 21, 2010, 8:01:47 AM4/21/10
to golang-nuts
On 20 Apr., 22:16, andrey mirtchovski <mirtchov...@gmail.com> wrote:
> however, you do need a guarantee
> that <-c blocks unless there's data on it for that to work, which is
> the snag you hit.

I think some kind of peek or unget function would be handy. This are
common operations for streams.

chris dollin

unread,
Apr 21, 2010, 8:09:14 AM4/21/10
to ceving, golang-nuts
On 21 April 2010 13:01, ceving <cev...@googlemail.com> wrote:
On 20 Apr., 22:16, andrey mirtchovski <mirtchov...@gmail.com> wrote:
> however, you do need a guarantee
> that <-c blocks unless there's data on it for that to work, which is
> the snag you hit.

I think some kind of peek or unget function would be handy. This are
common operations for streams.

Because you don't have goroutines.

--
Chris "allusive" Dollin

ceving

unread,
Apr 21, 2010, 8:48:08 AM4/21/10
to golang-nuts
On 21 Apr., 14:09, chris dollin <ehog.he...@googlemail.com> wrote:
>
> Because you don't have goroutines.
>

How can goroutines help if two channel should be read only if on both
channels is data available?

Ian Lance Taylor

unread,
Apr 21, 2010, 10:29:56 AM4/21/10
to ceving, golang-nuts
ceving <cev...@googlemail.com> writes:

> On 21 Apr., 14:09, chris dollin <ehog.he...@googlemail.com> wrote:
>>
>> Because you don't have goroutines.
>>
>
> How can goroutines help if two channel should be read only if on both
> channels is data available?

In a multi-goroutine program, a peek operation on a channel is prone
to race conditions. One goroutine might peek, make some decision, and
then some other goroutine might grab the value. The only reliable way
to read data from two channels at once is to do it atomically. The
language does not provide that operation, and providing it would be
prone to deadlock.

Instead, think of the problem differently. E.g., perhaps you could
put another goroutine in the path which uses select to pull one value
from each channel, puts them together, and sends the pair on a third
channel. Then the rest of your code will always see the objects in
pairs.

Ian
Reply all
Reply to author
Forward
0 new messages