WaitGroup
O altă posibilitate de sincronizare a gorutinelor este utilizarea tipului sync.WaitGroup. Acest tip permite definirea unui grup de gorutine care trebuie să ruleze împreună ca un singur grup. Se poate stabili o blocare care va întrerupe execuția funcției până când întregul grup de gorutine își încheie execuția. De exemplu:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup
wg.Add(2) // în grup sunt două gorutine
work := func(id int) {
defer wg.Done()
fmt.Printf("Gorutină %d a început executarea \n", id)
time.Sleep(2 * time.Second)
fmt.Printf("Gorutină %d a încheiat executarea \n", id)
}
// apelăm gorutinele
go work(1)
go work(2)
wg.Wait() // așteptăm finalizarea ambelor gorutine
fmt.Println("Gorutinele au încheiat execuția")
}
La început, definim grupul ca o variabilă wg de tip sync.WaitGroup. Folosind metoda Add, definim că grupul va conține două elemente:
wg.Add(2)
Numărul care se transmite în metoda Add definește valoarea contorului intern al elementelor active.
Toate elementele grupului wg vor reprezenta o funcție anonimă sub formă de variabilă work, care primește ca parametru un identificator numeric al gorutinei. Această funcție va fi apelată sub formă de gorutine. Pentru a semnala că un element al grupului și-a încheiat execuția, în gorutină trebuie să apelăm metoda Done():
defer wg.Done()
Apelul metodei wg.Done() reduce contorul intern al elementelor active cu câte 1.
În funcția work(), cu ajutorul unei întârzieri de două secunde (folosind time.Sleep(2 * time.Second)), se imită activitatea gorutinei.
Apoi, lansăm două gorutine:
go work(1)
go work(2)
Numărul de gorutine care apelează metoda wg.Done() trebuie să corespundă cu numărul de elemente din grupul wg, adică în acest caz 2 elemente.
După aceea, apelăm metoda Wait(), care așteaptă finalizarea tuturor gorutinelor din grupul wg:
wg.Wait()
Metoda deblochează funcția main atunci când contorul intern al elementelor active din grupul wg ajunge la 0. Prin urmare, când toate gorutinele din grupul wg își termină execuția, funcția main își continuă execuția.
Rezultatul execuției programului:
Gorutină 1 a început executarea
Gorutină 2 a început executarea
Gorutină 1 a încheiat executarea
Gorutină 2 a încheiat executarea
Gorutinele au încheiat execuția