fatal error: all goroutines are asleep - deadlock ,using channels

64 Views Asked by At

I am getting a deadlock error . I am not able to remove it . Kindly let me know where exactly i am making the mistake

package main

import (
    "fmt"
    "sync"
)

func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    var wg sync.WaitGroup

    wg.Add(2)
    go func() {
        defer wg.Done()
        b := 42
        ch1 <- b
        fmt.Println("ch1", ch1)
        wg.Wait()
        close(ch1)
    }()
    value := <-ch1
    fmt.Println("value", value)

    go func() {
        fmt.Println("enter", value)
        defer wg.Done()
        ch2 <- value
        a := <-ch2
        fmt.Println("ch2", a)
        wg.Wait()
        close(ch2)
    }()
    wg.Wait()
}

I worked on waitgroups and close of channels. It didnt work

1

There are 1 best solutions below

0
Anshu Kumar On

WaitGroup and Channels are means of synchronization and they work differently. Using both has messed.

  1. WaitGroup: It is a mechanism by which we can block the current go routine untill all tasks being performed by other go routine completes

    • wg.Add(num): It adds number of tasks to wait for.
    • wg.Done(): It reduces task count by one.
    • wg.Wait(): Holds current go routine till task counter reduces to 0.
  2. Channels: It is a communication medium across go routines. Reading an empty channel will block current go routine while writing to already full channel will also block the current routine. Writing and Reading same channel in same go routine will cause deadlock. As soon as something is written to a channel it waits to be read inside other go routine, if none is present, the program will deadlock. Closing a channel is not required unless sender explicitely wants to communicate that there is no more values to be sent. Sending on a closed channel will cause panic.

As far as I understood in above code snippet you are trying to send a value 42 to on ch1 in first go routine, then wants to read it in main go routine, then pass read value on another channel ch2 in another go routine and then read it finally in main go routine. Here is modified version of snippet that will help you do it.

package main

import (
    "fmt"
    "sync"
)

func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    var wg sync.WaitGroup

    wg.Add(2)
    go func() {
        defer wg.Done()
        b := 42
        ch1 <- b
        fmt.Println("ch1", ch1)
        close(ch1)
    }()
    value := <-ch1
    fmt.Println("value", value)

    go func() {
        fmt.Println("enter", value)
        defer wg.Done()
        ch2 <- value
        close(ch2)
    }()
    a := <-ch2
    fmt.Println("ch2", a)
    wg.Wait()
}