Checking completion

The preceding example technically works, but depending on a timer to wait for threads to complete isn't reliable. If the threads need to wait for a response or are part way through a long calculation, we'll still have potential corruption if the timer elapses. The solution is to have the goroutine signal once the cleanup is complete. This can be done with sync.WaitGroup or by using another channel.

For our completed thread example, we create sync.WaitGroup, which is passed to each of the tick threads. Before we start the goroutine, we increment the number of threads to wait on using wg.Add(1). Once each thread is complete, they mark that using wg.Done(). Our application is then free to call wg.Wait() immediately before exiting, safe in the knowledge that it won't prematurely terminate any of the grouped background processes.

The following code demonstrates signaling and waiting for multiple goroutines:

package main

import (
"fmt"
"sync"
"time"
)

func tickAndEnd(stop chan (struct{}), wg *sync.WaitGroup) {
wg.Add(1)
go func() {
fmt.Println("Started")

ticker := time.NewTicker(time.Second).C
for {
select {
case <-ticker:
fmt.Print(".")
case <-stop:
fmt.Println("Ended")
wg.Done()
return
}
}
}()
}

func main() {
stop := make(chan (struct{}))
wg := &sync.WaitGroup{}

tickAndEnd(stop, wg)
tickAndEnd(stop, wg)
tickAndEnd(stop, wg)

time.Sleep(5 * time.Second)
close(stop)

wg.Wait()
}

The output of this is almost exactly the same as the previous version, but the specific timing of the threads ending is slightly different:

Waiting for our goroutines to complete instead of waiting a set time
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.176.72