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 // releaseDlaczego 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
- Koncepcja wiadra tokenów
- golang.org/x/time/rate
- Ograniczanie goroutines
- Wycofywanie i ponawianie