İçeriğe geç

Wait Groups

sync.WaitGroup, goroutine’lerin tamamlanmasını beklemek için kullanılan bir senkronizasyon aracıdır.

WaitGroup 3 metoddan oluşur.

  1. Add(int): Beklenecek goroutine sayısına parametrede belirtilen sayı kadar ekleme yapar.
  2. Done(): Beklenilen goroutine sayısını bir azaltır. Goroutine’in tamamlanmasını temsilen kullanılır.
  3. Wait(): Tüm Goroutine’ler tamamlanana kadar beklemek için kullanılır.

Örnek Bir Senaryo

main.go
1
package main
2
3
import (
4
"fmt"
5
"sync"
6
"time"
7
)
8
9
func main() {
10
wg := sync.WaitGroup{}
11
12
for i := range 3 {
13
wg.Add(1)
14
go doSomething(i, &wg)
15
}
16
17
wg.Wait()
18
19
fmt.Println("all finished")
20
}
21
22
func doSomething(i int, wg *sync.WaitGroup) {
23
time.Sleep(3 * time.Second)
24
fmt.Println(i, "finished")
25
wg.Done()
26
}

WaitGroup’ları kullanabilmek için 5. satırda sync paketini import ettik. 10. satırda bir WaitGroup oluşturduk. 3 adımlı bir döngü içerisinde WaitGroup’a birer birer toplamda 3 ekleme yaptık. Bu eklemelerin herbirini 14. satırda açılan goroutine’ler için kullanılıyoruz. doSomething fonksiyonu içerisinde formaliteden bekletip işlemin bittiğinib çıktısını yazdırdık ve wg.Done() ile WaitGroup’tan bir eksilttik.

doSomething fonksiyonunun imazsında dikkat etmemiz gereken bir bölüm var. WaiyGroup’u işaretçi ile yolladık. Çünkü 14. satırda parametre olarak yollarken işaretçi ile yollamazsak, WaitGroup kopyalanacağı için 25. satırda asıl WaitGroup’tan bir eksiltemezdik. Bu yüzden WaitGroup’u init ettikten sonra işaretçi ile kullanmayı alışkanlık haline getirelim.

Bunu yapmanın pratik bir yolunu yörelim.

wg := new(sync.WaitGroup) // *sync.WaitGroup
// new ile init edip işaretçisini almış olduk
// blah blah blah
doSomething(i /* int */, wg /* *sync.WaitGroup */)

17.. satırda wg.Wait() kullanarak WaitGroup içerisindeki sayı sıfırlanana kadar, yani Add(int) ile eklenilen tüm sayıların toplamı kadar Done() çalıştırılana kadar beklemiş olduk.

Canlı Demo

0 Beklenilecek Goroutine Sayısı
Wait()