← Назад ко всем вопросам

Как дождаться выполнения нескольких горутин

1️⃣ Как кратко ответить

Для ожидания выполнения нескольких горутин в Go используется sync.WaitGroup. Он позволяет отслеживать количество активных горутин и блокировать выполнение основной программы до тех пор, пока все горутины не завершатся.

2️⃣ Подробное объяснение темы

В языке программирования Go горутины — это легковесные потоки, которые позволяют выполнять функции параллельно. Однако, когда вы запускаете несколько горутин, может возникнуть необходимость дождаться их завершения перед продолжением выполнения основной программы. Для этого в Go используется структура sync.WaitGroup.

Зачем это нужно

Когда вы запускаете несколько горутин, они выполняются асинхронно. Если основная программа завершится раньше, чем горутины, то они могут быть прерваны, и их работа не будет завершена. sync.WaitGroup позволяет синхронизировать выполнение, гарантируя, что основная программа дождется завершения всех горутин.

Как это работает

sync.WaitGroup предоставляет три основных метода:

  • Add(delta int): увеличивает счетчик горутин на указанное количество.
  • Done(): уменьшает счетчик на единицу, сигнализируя о завершении одной горутины.
  • Wait(): блокирует выполнение до тех пор, пока счетчик не станет равным нулю.

Пример использования

Рассмотрим пример, где мы запускаем несколько горутин и ждем их завершения:

package main
​
import (
	"fmt"
	"sync"
	"time"
)
​
func worker(id int, wg *sync.WaitGroup) {
	defer wg.Done() // Уменьшает счетчик на 1, когда горутина завершает выполнение
	fmt.Printf("Worker %d starting\n", id)
	time.Sleep(time.Second) // Симулирует работу, которая занимает 1 секунду
	fmt.Printf("Worker %d done\n", id)
}
​
func main() {
	var wg sync.WaitGroup // Создаем экземпляр WaitGroup
​
	const numWorkers = 5
	wg.Add(numWorkers) // Устанавливаем счетчик равным количеству горутин
​
	for i := 1; i <= numWorkers; i++ {
		go worker(i, &wg) // Запускаем горутину и передаем указатель на WaitGroup
	}
​
	wg.Wait() // Блокируем выполнение до тех пор, пока все горутины не вызовут Done()
	fmt.Println("All workers done")
}

Пояснение к коду

  1. Импортируем пакеты: fmt для вывода в консоль, sync для использования WaitGroup, и time для симуляции задержки.

  2. Функция worker: принимает идентификатор и указатель на WaitGroup.

    • defer wg.Done(): гарантирует, что счетчик уменьшится на 1, когда функция завершится.
    • fmt.Printf: выводит сообщение о начале и завершении работы.
    • time.Sleep: симулирует выполнение задачи, задерживая выполнение на 1 секунду.
  3. Функция main:

    • Создает экземпляр WaitGroup.
    • Устанавливает счетчик WaitGroup равным количеству горутин с помощью wg.Add(numWorkers).
    • Запускает numWorkers горутин, передавая каждой идентификатор и указатель на WaitGroup.
    • wg.Wait(): блокирует выполнение основной программы до тех пор, пока все горутины не завершатся.

Этот механизм позволяет эффективно управлять параллельным выполнением задач в Go, обеспечивая корректное завершение всех горутин перед продолжением выполнения основной программы.

Тема: Конкурентность
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки