#19.2 golang Синхронизация работы горутин через WaitGroup, объединение в группы

Для синхронизации выполнения горутин в Go имеется пакет sync, в нем в частности, определена стандартная структура sync.WaitGroup.

Тип sync.WaitGroup позволяет объединять горутины в группы и установливать блокировку, которая приостановит выполнение родительской (по отношению к вызванным горутинам функции) функции, пока не завершит выполнение вся группа горутин.

Рассмотрим пример кода:

package main

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

func doAsync(id int, wg *sync.WaitGroup) {
	fmt.Printf("Горутина %d начала выполнение \n", id)
	time.Sleep(200 * time.Microsecond) // задержка
	fmt.Printf("Горутина %d завершила выполнение \n", id)
	wg.Done() // сигнализируем, что горутина завершила работу
}

func main() {

	list := []int{1, 2, 3}
	var wg sync.WaitGroup
	wg.Add(len(list)) // задаем количество горутин в группе

	// вызываем горутины для каждого значения
	for _, value := range list {
		go doAsync(value, &wg)
	}

	wg.Wait() // ожидаем завершения всех горутин группы
	fmt.Println("Конец!")
}

-- здесь мы:

  • используем переменную wg типа sync.WaitGroup для задания группы - количество определяем динамически через len()
  • указываем сколько именно горутин будет в группе
  • проходимся циклом по срезу значений и для каждого вызываем горутину
  • чтобы внутри функции работать с той же группой, а не с копией, передаем значение wg в doAsync() через указатель

-- если запустим код, то получим распечатку вида:

Горутина 3 начала выполнение 
Горутина 2 начала выполнение 
Горутина 1 начала выполнение 
Горутина 3 завершила выполнение 
Горутина 1 завершила выполнение 
Горутина 2 завершила выполнение 
Конец!

Источники