Deadlock while sending data to channel in slice of channels

Viewed 99

Sending data to integer channel in slice of channels is resulting into deadlock

The code is expected to create 5 (+1 fanInChan) channels. These channels are used for send integer values through send() and receive the same in receive() and finally Fan-in the them to fanInChan.

Code:-

package main

import (
    "fmt"
    "sync"
)

func main() {
    defer fmt.Println("About to exit!")
    fmt.Println("Started")

    channels := make([]chan int, 5)
    fanInChan := make(chan int)

    go send(channels)
    go recive(fanInChan, channels)

    for val := range fanInChan {
        fmt.Println("Fanin", val)
    }
}
func send(channels []chan int) {
    defer fmt.Println("Send Ended")
    fmt.Println("Send Started")

    for i := 0; i < 100; i++ {
        channels[i%5] <- i
    }

    for i := 0; i < 5; i++ {
        close(channels[i])
    }
}

func recive(fanin chan<- int, channels []chan int) {
    defer fmt.Println("Recive Ended")
    fmt.Println("Recive Started")

    var wg sync.WaitGroup
    wg.Add(5)

    for i := 0; i < 5; i++ {
        go func(inew int) {
            defer wg.Done()
            fmt.Println(inew)
            for v := range channels[inew] {
                fanin <- v
            }
        }(i)
    }

    wg.Wait()
    close(fanin)
}

Golang PlayGround

OutPut:-

Started
Send Started
Recive Started
4
1
2
3
0
fatal error: all goroutines are asleep - deadlock!
... //You can see rest on playground link above

Problem is starting in a for loop inside send()

for i := 0; i < 100; i++ {
        channels[i%5] <- i
    }

1 Answers

The statement channels := make([]chan int, 5) is allocating a array with nil channels which

  • Blocks receiving <- channel from channel
  • Blocks sending channel <- value into channel
  • panics on closing close(channel)

So you have to initialize each channel individually to recive integer values.

You should init the channels in the channels array before using those.

    for i := range channels {
        channels[i] = make(chan int)
    }

Insert this just before the line go send(channels) and run.

Related