Go został zaprojektowany z myślą o pisaniu wydajnych programów sieciowych i równoległych, dlatego szczególną uwagę poświęcono wbudowanemu planista (scheduler) i prostemu zarządzaniu równoległością za pomocą gorutin. W przeciwieństwie do większości języków, w których wątki OS są bezpośrednio zarządzane przez użytkownika języka, w Go gorutyny są lżejsze, ich tysiące mogą działać jednocześnie na ograniczonej liczbie wątków systemowych.
Problem: bezpośrednie zarządzanie wątkami (threads) jest skomplikowane: prowadzi to do szybkiej utylizacji zasobów, data races i trudności w zarządzaniu pamięcią.
Rozwiązanie: Go używa modelu M:N — duża liczba gorutin (M) jest multiplikowana na ograniczonej liczbie wątków OS (N). Za to odpowiada planista, zrealizowany na poziomie runtime Go, który automatycznie równoważy i przesmakuje wykonanie gorutin. Programista zarządza tylko uruchamianiem i synchronizacją gorutin, a nie bezpośrednio wątkami OS.
Przykład kodu:
package main import ( "fmt" "time" ) func worker(id int) { fmt.Printf("Pracownik %d zaczyna ", id) time.Sleep(time.Second) fmt.Printf("Pracownik %d wykonany ", id) } func main() { for i := 0; i < 5; i++ { go worker(i) } time.Sleep(2 * time.Second) }
Kluczowe cechy:
Czy każda gorutyna będzie wykonywana równolegle na osobnym rdzeniu procesora?
Nie. Gorutyny są multiplikowane, a planista określa rzeczywistą liczbę jednocześnie wykonywanych zadań.
Czy można ręcznie zarządzać wykonaniem konkretnych gorutin/wątków?
Nie. Runtime Go nie udostępnia interfejsu do bezpośredniego planowania. Wyjątek — GOMAXPROCS do ustawienia liczby wątków OS.
Czy duża liczba gorutin oznacza automatyczne przyspieszenie programu?
Nie. Wysoka liczba konkurencyjnych operacji może prowadzić do dodatkowych obciążeń: przełączania kontekstu, rywalizacji o zasoby, wzrostu czasu GC i zużycia pamięci.
Mikrousługa równolegle przetwarzała przychodzące zapytania, nie ograniczała liczby gorutin i nie czekała na zakończenie przez WaitGroup — rezultat: wydłużony czas odpowiedzi, data races, nieprzewidywalne czasami.
Plusy:
Minusy:
Menadżer wątków został zrealizowany przez pulę gorutin, ograniczenie liczby jednocześnie działających zadań — przez semafor lub kanały. WaitGroup poprawnie czeka na zakończenie wszystkich zadań.
Plusy:
Minusy: