0Pricing
Go Academy · Lekcja

Ograniczanie goroutines

Steruj współbieżnością

Ograniczanie goroutines to bezpłatna lekcja Go Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Go Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Go Academy zawiera 4 lekcji w sumie.

Ograniczanie współbieżności

Czasami nie ogranicza się liczby operacji na sekundę, lecz liczbę goroutines uruchomionych jednocześnie. Ogranicza to równoczesne obciążenie zasobu niezależnie od czasu wykonania operacji.

  • Ogranicza równoległość
  • Chroni pule połączeń
  • Zapobiega skokom zużycia pamięci

Kanał jako semafor

Buforowany kanał działa jak semafor zliczający. Jego pojemność określa maksymalną współbieżność. Przejęcie miejsca polega na wysłaniu tokenu, a jego zwolnienie — na odebraniu tokenu.

sem := make(chan struct{}, 3)

Przejmowanie i zwalnianie

Przed rozpoczęciem pracy należy wysłać wartość do kanału, aby przejąć miejsce (operacja blokuje się, gdy kanał jest pełny). Po zakończeniu pracy należy odebrać wartość, aby zwolnić miejsce dla kolejnej goroutine.

sem <- struct{}{}        // acquire
// do work
<-sem                    // release

Dlaczego struct{}

Pusta struktura struct{}{} zajmuje zero bajtów. Użycie jej jako typu elementu kanału sprawia, że semafor jest wyłącznie sygnałem i nie marnuje pamięci.

Ograniczanie pętli

Należy uruchomić jedną goroutine dla każdego zadania, ale uzależnić rozpoczęcie pracy od semafora. Jednocześnie rzeczywistą pracę wykonuje najwyżej cap goroutines; pozostałe blokują się podczas przejmowania miejsca.

for _, task := range tasks {
    sem <- struct{}{}
    go func(t Task) {
        defer func() { <-sem }()
        process(t)
    }(t)
}

Połączenie z WaitGroup

Semafor ogranicza współbieżność, ale nie informuje, kiedy wszystkie zadania się zakończą. Należy połączyć go z sync.WaitGroup, aby zaczekać na ukończenie wszystkich zadań.

var wg sync.WaitGroup
wg.Add(1)
go func() {
    defer wg.Done()
    defer func() { <-sem }()
    process(t)
}()

Zwalnianie w defer

Miejsce należy zawsze zwalniać w defer, aby zostało uwolnione nawet wtedy, gdy praca wywoła panikę lub zakończy się wcześniej. Pominięcie zwolnienia wycieka miejscami i ostatecznie prowadzi do zakleszczenia nowych operacji przejmujących miejsce.

Kompletne ograniczone uruchomienie

Ten program uruchamia osiem zadań, z których jednocześnie wykonywane są najwyżej dwa. Wypisywanie początku i końca pracy pokazuje działanie ograniczenia.

package main

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

func main() {
    sem := make(chan struct{}, 2)
    var wg sync.WaitGroup
    for i := 0; i < 8; i++ {
        wg.Add(1)
        sem <- struct{}{}
        go func(id int) {
            defer wg.Done()
            defer func() { <-sem }()
            fmt.Println("start", id)
            time.Sleep(20 * time.Millisecond)
            fmt.Println("end", id)
        }(i)
    }
    wg.Wait()
    fmt.Println("done")
}

errgroup z SetLimit

Pakiet golang.org/x/sync/errgroup udostępnia SetLimit, które ogranicza współbieżność grupy i przekazuje pierwszy błąd. W wielu przypadkach jest to prostsza alternatywa, choć pakiet ten jest zewnętrzny.

Ograniczanie a pula workerów

Pula workerów ponownie wykorzystuje stały zestaw goroutines pobierających zadania z kolejki. Ograniczanie za pomocą semafora uruchamia goroutine dla każdego zadania, ale ogranicza liczbę aktywnych goroutines. Pule są oszczędniejsze przy ogromnej liczbie zadań, natomiast semafory łatwiej dołączyć do istniejącego kodu.

Wybór limitu

W przypadku wywołań bazy danych należy ustawić limit na poziomie rozmiaru puli połączeń lub niższym. Dla wychodzących żądań HTTP należy dopasować go do limitu połączeń z hostem. Zbyt wysoki limit wyczerpuje zasoby, a zbyt niski marnuje dostępną wydajność.

Szybkie sprawdzenie

Sprawdź swoją wiedzę o ograniczaniu współbieżności.

Podsumowanie

Poznali Państwo ograniczanie goroutines:

  • Buforowany kanał działa jak semafor zliczający
  • Miejsce przejmuje się przez wysłanie, a zwalnia przez odebranie w defer
  • Elementy typu struct{} zajmują zero bajtów
  • WaitGroup pozwala zaczekać na ukończenie pracy
  • Rozmiar limitu należy dopasować do chronionego zasobu

Często zadawane pytania

Czy lekcja „Ograniczanie goroutines” jest bezpłatna?

Tak — pełny tekst „Ograniczanie goroutines” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Go Academy, przejdź na CoddyKit PRO. Kurs Go Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Ograniczanie goroutines”?

Steruj współbieżnością Ćwiczysz Go Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Go Academy?

Nie wymagamy żadnego doświadczenia. Go Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Ograniczanie goroutines”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Go Academy?

Tak. Każda lekcja Go Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Koncepcja wiadra tokenów
  2. golang.org/x/time/rate
  3. Ograniczanie goroutines
  4. Wycofywanie i ponawianie
← Powrót do Go Academy