Waitgroups: координация параллельных горутин

GolangGolangBeginner
Практиковаться сейчас

This tutorial is from open-source community. Access the source code

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

Лабораторная работа по waitgroups создана для того, чтобы помочь вам понять, как использовать группу ожидания для ожидания завершения нескольких горутин.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/ConcurrencyGroup(["Concurrency"]) go/ConcurrencyGroup -.-> go/waitgroups("Waitgroups") subgraph Lab Skills go/waitgroups -.-> lab-15529{{"Waitgroups: координация параллельных горутин"}} end

waitgroups

Проблема, которую необходимо решить в этой лабораторной работе, заключается в том, чтобы запустить несколько горутин и увеличить счетчик WaitGroup для каждой из них. Затем нам нужно дождаться завершения всех запущенных горутин.

  • Основные знания Golang.
  • Понимание параллелизма в Golang.
  • Знание пакета sync.
$ go run waitgroups.go
Worker 5 starting
Worker 3 starting
Worker 4 starting
Worker 1 starting
Worker 2 starting
Worker 4 done
Worker 1 done
Worker 2 done
Worker 5 done
Worker 3 done

## Порядок запуска и завершения воркеров
## может различаться при каждом вызове.

Ниже представлен полный код:

// Чтобы дождаться завершения нескольких горутин, мы можем
// использовать *группу ожидания*.

package main

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

// Эта функция будет выполняться в каждой горутине.
func worker(id int) {
	fmt.Printf("Worker %d starting\n", id)

	// Сон, чтобы имитировать дорогостоящую задачу.
	time.Sleep(time.Second)
	fmt.Printf("Worker %d done\n", id)
}

func main() {

	// Эта WaitGroup используется для ожидания завершения всех
	// горутин, запущенных здесь. Примечание: если WaitGroup явно
	// передается в функции, то это должно быть *по указателю*.
	var wg sync.WaitGroup

	// Запустить несколько горутин и увеличить счетчик WaitGroup
	// для каждой.
	for i := 1; i <= 5; i++ {
		wg.Add(1)
		// Избегать повторного использования одного и того же значения `i`
		// в каждой замыкании горутины.
		// См. [часто задаваемые вопросы](https://golang.org/doc/faq#closures_and_goroutines)
		// для получения более подробной информации.
		i := i

		// Обернуть вызов воркера в замыкание, которое гарантирует, что
		// WaitGroup будет уведомлен о том, что этот воркер завершен. Таким
		// образом, сам воркер не должен знать о примитивах параллелизма,
		// участвующих в его выполнении.
		go func() {
			defer wg.Done()
			worker(i)
		}()
	}

	// Блокировка до тех пор, пока счетчик WaitGroup не вернется в 0;
	// все воркеры были уведомлены о том, что они завершились.
	wg.Wait()

	// Примечание: этот подход не имеет простого способа
	// распространять ошибки из воркеров. Для более
	// сложных сценариев использования рассмотрите
	// пакет [errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup).
}

Резюме

В этой лабораторной работе мы узнали, как использовать группу ожидания для ожидания завершения нескольких горутин. Мы также узнали, как запускать несколько горутин и увеличивать счетчик WaitGroup для каждой. Наконец, мы увидели, как дождаться завершения всех запущенных горутин.