Wzorzec semafora
Ograniczanie współbieżności za pomocą semafora opartego na kanale
Wzorzec semafora 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.
Czym jest semafor?
Semafor ogranicza liczbę goroutines wykonujących daną operację równocześnie. Zapobiega wyczerpaniu zasobów (np. zbyt dużej liczbie otwartych połączeń z bazą danych lub wychodzących żądań HTTP).
Buforowany kanał jako semafor
Buforowany kanał o pojemności N działa jak semafor zliczający. Zajęcie zasobu polega na wysłaniu wartości do kanału (operacja blokuje się, gdy kanał jest pełny), a jego zwolnienie — na odebraniu wartości z kanału.
sem := make(chan struct{}, 10)
func withSem(f func()) {
sem <- struct{}{} // acquire
defer func() { <-sem }() // release
f()
}Jedna goroutine na zadanie z semaforem
Należy uruchomić jedną goroutine dla każdego zadania, ale ograniczyć współbieżność za pomocą semafora:
sem := make(chan struct{}, 5)
for _, job := range jobs {
sem <- struct{}{}
go func(j Job) {
defer func() { <-sem }()
process(j)
}(job)
}Opróżnianie semafora na końcu
Po uruchomieniu wszystkich goroutines należy opróżnić semafor, aby upewnić się, że wszystkie zakończyły pracę przed powrotem funkcji:
// After the loop, acquire all N slots (blocks until all goroutines release)
for i := 0; i < cap(sem); i++ {
sem <- struct{}{}
}golang.org/x/sync/semaphore
W przypadku semafora ważonego (np. dla goroutines o różnym zapotrzebowaniu na zasoby) należy użyć typu semaphore.Weighted:
s := semaphore.NewWeighted(100)
// acquire 10 units
if err := s.Acquire(ctx, 10); err != nil { return err }
defer s.Release(10)
// do workPobieranie z uwzględnieniem context
Metoda Acquire semafora ważonego respektuje context i zwraca błąd, jeśli zostanie on anulowany, zanim semafor stanie się dostępny.
TryAcquire
s.TryAcquire(n) zajmuje n jednostek tylko wtedy, gdy są one natychmiast dostępne, a w przeciwnym razie zwraca false. Jest przydatna podczas nieblokujących sprawdzeń.
Semafor a pula pracowników
Pula pracowników ma stały zestaw trwałych goroutines. Semafor pozwala uruchamiać goroutines na żądanie, jednocześnie ograniczając współbieżność. Semafor warto stosować, gdy tempo napływu zadań znacznie się zmienia.
Ograniczanie współbieżności HTTP
Należy opakować obsługę HTTP lub klienta HTTP semaforem, aby zapobiec zbyt dużej liczbie równoczesnych wychodzących żądań lub goroutines obsługujących żądania przychodzące.
Ograniczanie połączeń z bazą danych
Zamiast semafora należy ustawić db.SetMaxOpenConns(n) i db.SetMaxIdleConns(m) — pakiet sql sam zarządza współbieżnością puli połączeń.
Sprawiedliwość semafora
Semafory oparte na buforowanych kanałach są w przybliżeniu sprawiedliwe (FIFO dla goroutines zablokowanych podczas wysyłania), ale nie jest to ściśle gwarantowane. Pakiet semafora ważonego zapewnia silniejsze gwarancje sprawiedliwości.
Szybki test
W jaki sposób buforowany kanał implementuje semafor?
Podsumowanie: wzorzec semafora
Najważniejsze informacje:
- Buforowany kanał sem := make(chan struct{}, N) do implementowania prostych semaforów
- Wysyłanie służy do uzyskania dostępu, odbieranie do jego zwolnienia; zwolnienie należy zawsze odroczyć za pomocą defer
- golang.org/x/sync/semaphore dla wariantu ważonego obsługującego kontekst
- errgroup.SetLimit do ustawiania prostych limitów współbieżności dla grup
Często zadawane pytania
Czy lekcja „Wzorzec semafora” jest bezpłatna?
Tak — pełny tekst „Wzorzec semafora” 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 „Wzorzec semafora”?
Ograniczanie współbieżności za pomocą semafora opartego na kanale Ć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 „Wzorzec semafora”?
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
- Wzorce potoków i etapów
- errgroup do współbieżnej obsługi błędów
- Wzorzec semafora
- Wykrywanie wycieków i anulowanie