Unable to find reason for go deadlock

Issue

Unable to find a reason as to why this code deadlocks. The aim here is make the worker go routines do some work only after they are signaled.

If the signalStream channel is removed from the code, it works fine. But when this is introduced, it deadlocks. Not sure the reason for this. Also if there are any tools to explain the occurrence of deadlock, it would help.

package main

import (
    "log"
    "sync"
)

const jobs = 10
const workers = 5

var wg sync.WaitGroup

func main() {

    // create channel
    dataStream := make(chan interface{})
    signalStream := make(chan interface{})

    // Generate workers

    for i := 1; i <= workers; i++ {
        wg.Add(1)
        go worker(dataStream, signalStream, i*100)
    }

    // Generate jobs

    for i := 1; i <= jobs; i++ {
        dataStream <- i
    }
    close(dataStream)

    // start consuming data
    close(signalStream)

    wg.Wait()

}

func worker(c <-chan interface{}, s <-chan interface{}, id int) {
    defer wg.Done()
    <-s

    for i := range c {
        log.Printf("routine - %d - %d \n", id, i)
    }

}

Solution

Generate the jobs in a separate gorouine, i.e. put the whole jobs loop into a goroutine. If you don’t then dataStream <- i will block and your program will never "start consuming data"

// Generate jobs
go func() {
    for i := 1; i <= jobs; i++ {
        dataStream <- i
    }
    close(dataStream)
}()

https://go.dev/play/p/ChlbsJlgwdE

Answered By – mkopriva

Answer Checked By – Jay B. (GoLangFix Admin)

Leave a Reply

Your email address will not be published.