Reputation: 755
I am facing a bit of a concurrency issue. I am writing a concurrent application for the first time.
Dependent functions ( using goroutines ) i.e. func2
is dependent on the result of func1
If I reuse the waitgroup after it's done waiting I get an error as
fatal error: all goroutines are asleep - deadlock!
Here's my code ( Playground ) :
package main
import (
"fmt"
"sync"
"time"
)
func main() {
wg := sync.WaitGroup{}
ch := make(chan int)
for a := 0; a < 3; a++ {
wg.Add(1)
go func1(int(3-a), ch, &wg)
}
go func() {
wg.Wait()
close(ch)
}()
//wg2 := sync.WaitGroup{} //<-- If I uncomment this and the corresponding wg2 code, then the snippet runs fine
ch2 := make(chan string)
for val := range ch {
fmt.Println(val)
wg.Add(1)
//wg2.Add(1)
go func2(val, ch2, &wg)
//go func2(val, ch2, &wg2)
}
go func() {
wg.Wait()
//wg2.Wait()
close(ch2)
}()
for val := range ch2 {
fmt.Println(val)
}
}
func func1(seconds int, ch chan<- int, wg *sync.WaitGroup) {
defer wg.Done()
time.Sleep(time.Duration(seconds) * time.Second)
ch <- seconds
}
func func2(seconds int, ch chan<- string, wg *sync.WaitGroup) {
defer wg.Done()
ch <- "hello"
}
So, you can see, if I create a new WaitGroup
it works fine else deadlock arises.
Thanks
Temporarya
( A golang noobie )
Upvotes: 0
Views: 689
Reputation: 273416
WaitGroups can be safely reused but it's not clear why you're using a third-party package for this? Especially if you're just learning concurrency, I would strongly recommend you to stick to the standard library - sync.WaitGroup
is what you need.
FWIW, if I modify your code to use sync.WaitGroup
, it doesn't deadlock and runs to completion - see this playground
This Go blog post explains how to do pipelining safely with channels, and in some more advanced cases wait groups (you don't always need them)
Upvotes: 2