scott
scott

Reputation: 1637

Hung goroutines when comparing two slices in two separate goroutines and using sync.Waitgroup

I was learning goroutines, and was comparing two slices to each other in two goroutines, which is in an infinite loop to compare it forever, which may not be the best example to use, and I couldn't figure out why it is hung.

for ;; {
    var wg sync.WaitGroup
    wg.Add(2)
    go FindinFirst(&Arr1, &Arr2, AddChan, &wg)
    go FindinSecond(&Arr2, &Arr1, DelChan, &wg)
    counter := 0
        for ; ; {
            select {
            case Add, ok := <- AddChan:
                if ok == true {
                    for k, v := range Add  {
                        fmt.Println(k, ":", v)
                    }
                }else {
                    counter += 1
                }
            case Del, ok := <- DelChan:
                if ok == true {
                    for k, v := range Del  {
                        fmt.Println(k, ":", v)
                    }
                }else {
                    counter += 1
                    }
            }
            if counter == 2{
                break
            }
            wg.Wait()
}

Function FindinFirst is

func FindinFirst(Arr1, Arr2 *[]string, AddChan chan string, wg *sync.WaitGroup){
defer wg.Done()
fmt.Println("Starting FindinFirst")
defer close(AddChan)
for _, i := range *Arr1 {
    if IfExists(i, *Arr2) {
        fmt.Println("Exists")
        continue
    } else {
        AddChan <- i

    }
}
}

Function FindinSecond is

func FindinSecond(Arr2, Arr1 *[]string, DelChan chan string, wg *sync.WaitGroup){
defer wg.Done()
fmt.Println("Starting FindinSecond")
defer close(DelChan)
for _, i := range *Arr2 {
    if IfExists(i, *Arr1) {
        fmt.Println("Exists")
        continue
    } else {
        DelChan <- i

    }
}
}

And IfExists is just a function which return a bool if the value exists in the slice.

However, the routine is stuck with just one value that is being printed, and I am not sure why it is happening. Both the slices has close to 1000 values, and both has uniques. What is wrong with the code?

Upvotes: 0

Views: 93

Answers (1)

Sriharsha
Sriharsha

Reputation: 2443

I don't think there is any use of using wait groups here... Since you are consuming the channels inside a for loop, putting wg.wait() will block untill all the wait groups are completed.

In this cases, putting a value into AddChan will block unless some one is waiting for it. The code works just for first case, after which it hangs.

You can remove the wg.wait() and outer for loop and it will work.

func main() {
    Arr1 := []string{"a", "b", "c", "d"}
    Arr2 := []string{"c", "e", "f", "g"}
    AddChan := make(chan string)
    DelChan := make(chan string)

    var wg sync.WaitGroup
    wg.Add(2)
    go FindinFirst(&Arr1, &Arr2, AddChan, &wg)
    go FindinSecond(&Arr2, &Arr1, DelChan, &wg)
    counter := 0
    for {
        select {
        case Add, ok := <-AddChan:
            if ok == true {
               fmt.Println(Add)
            } else {
                counter += 1
            }
        case Del, ok := <-DelChan:
            if ok == true {
                fmt.Println(Del)
            } else {
                counter += 1
            }
        }

        //if both the channels are closed, we are good, hence exit
        if counter == 2 {
            break
        }
    }
}

Upvotes: 2

Related Questions