среда, 16 октября 2019 г.

Использование sync.WaitGroup для ожидания завершения нескольких goroutine

WaitGroup ожидает завершения коллекции goroutine. Основная goroutine вызывает Add, чтобы установить количество goroutine, которых необходимо ожидать. Затем каждая из goroutine запускается и вызывает Done, когда завершается. В то же время, Wait может быть использован, чтобы блокировать, пока все goroutine не завершились.

WaitGroup нельзя копировать после первого использования.

В следующем примере выполняются конкурентные запросы по нескольким URL-адресам с использованием WaitGroup для блокировки исполнения до тех пор, пока все запросы не будут завершены.

package main

import (
  "fmt"
  "sync"
)

type httpPkg struct{}

func (httpPkg) Get(url string) {}

var http httpPkg

func main() {
  var wg sync.WaitGroup
  var urls = []string{
    "http://www.golang.org/",
    "http://www.google.com/",
    "http://www.example.com/",
  }
  fmt.Println("Начинаем выполнять запросы")
  for _, url := range urls {
    // Увеличиваем WaitGroup счетчик.
    wg.Add(1)
    // Запускаем  goroutine для выполения запроса по URL.
    go func(url string) {
      // Уменьшаем счетчик когда goroutine завершается.
      defer wg.Done()
      // Выполеняем запрос по URL.
      http.Get(url)
      fmt.Println(url)
    }(url)
  }
  // Ожидаем пока все HTTP запросы завершатся.
  wg.Wait()
  fmt.Println("Все запросы выполнены")
}

Вывод:

Начинаем выполнять запросы
http://www.example.com/
http://www.golang.org/
http://www.google.com/
Все запросы выполнены

Запустить пример в песочнице play.golang.org

Метод func(*WaitGroup) Add

func (wg *WaitGroup) Add(delta int)

Add добавляет delta, которая может быть отрицательной, к счетчику WaitGroup. Если счетчик обнуляется, все goroutine, заблокированные Wait, освобождаются. Если счетчик становится отрицательным, Add вызывает panic.

Обратите внимание, что вызовы с положительной delta, которые происходят, когда счетчик равен нулю, должны происходить до Wait. Вызовы с отрицательной delta или вызовы с положительной delta, которые начинаются, когда счетчик больше нуля, могут происходить в любое время. Как правило, это означает, что вызовы Add должны выполняться перед утверждением, создающим goroutine или другим событием, которое следует ожидать. Если WaitGroup повторно используется для ожидания нескольких независимых наборов событий, новые вызовы Add должны произойти после того, как все предыдущие вызовы Wait будут возвращены.

Метод func(*WaitGroup) Done

func (wg *WaitGroup) Done()

Done уменьшает счетчик WaitGroup на один.

Метод func(*WaitGroup) Wait

func (wg *WaitGroup) Wait()

Wait блокирует исполнение потока до тех пор пока счетчик WaitGroup не обнулится.


Читайте также:


Комментариев нет:

Отправить комментарий