I have an application where I am creating multiple goroutines to perform a certain task concurrently. All worker goroutines wait for a condition/event to occur and once the event is triggered, they begin their execution. After creating all goroutines, the main thread should know that all goroutines are indeed in waiting state before sending a broadcast signal.
I know this can be done using channels (which is something that is recommended) but I also found go's sync package interesting. Just trying to figure out how to achieve the same functionality using the sync package instead of channels
package main
import (
"fmt"
"sync"
"time"
)
var counter int
func worker(wg *sync.WaitGroup, cond *sync.Cond, id int) {
fmt.Println("Starting Goroutine ID:", id)
// Get a lock and wait
cond.L.Lock()
defer cond.L.Unlock()
fmt.Println("Goroutine with ID: ", id, "obtained a lock")
// Do some processing with the shared resource and wait
counter++
wg.Done()
cond.Wait()
fmt.Println("Goroutine ID:", id, "signalled. Continuing...")
}
func main() {
var wg sync.WaitGroup
cond := sync.NewCond(&sync.Mutex{})
counter = 0
for i := 0; i < 5; i++ {
wg.Add(1)
go worker(&wg, cond, i)
}
wg.Wait() // Wait()'ing only until the counter is incremented
// How to make sure that all goroutines you created are indeed wait()'ing ?????
cond.Broadcast()
time.Sleep(2 * time.Second)
cond.Broadcast()
fmt.Println("Final value of the counter is", counter)
}
If I don't use the below statements in the last 3 lines (except the fmt.Println)
time.Sleep(2 * time.Second)
cond.Broadcast()
I get the below output..
Starting Goroutine ID: 4
Goroutine with ID: 4 obtained a lock
Starting Goroutine ID: 3
Goroutine with ID: 3 obtained a lock
Starting Goroutine ID: 1
Goroutine with ID: 1 obtained a lock
Starting Goroutine ID: 0
Goroutine with ID: 0 obtained a lock
Starting Goroutine ID: 2
Goroutine with ID: 2 obtained a lock
Final value of the counter is 5
Goroutine ID: 3 signalled. Continuing...
Ideally every goroutine should be able to print
Goroutine ID: 3 signalled. Continuing...
with the corresponding goroutine id. We are not able to print that because not all goroutines are signalled as some of them are not even in the wait state. That is the reason I added time.Sleep which is not a practical solution.
My question is..How can I know that all goroutines are actually waiting on the condition cond.Wait()..Channels is a solution but I want to know how I could do this using go's sync package?