Middle+
Ispričajte o planiranju goroutine u Go.
sobes.tech АИ
Одговор од АИ
Planer gorutina u Go koristi model M:N, gde je M gorutina mapirano na N niti OS-a. Efikasno prebacuje gorutine između niti, implementirajući neprimenjivu multitaskingu sa tačkama zaustavljanja (preemption points).
Glavne komponente GPM modela:
- G (Goroutine): Apstrakcija izvršne jedinice koda, lagani tok, upravljan od strane planera Go.
- P (Processor): Logički procesor, predstavljajući kontekst lokalne reda gorutina i resursa kao što su muteksi i planer. Broj P je podrazumevano određen brojem logičkih jezgara procesora, ali može biti promenjen putem
GOMAXPROCS. - M (Machine/Thread): Tok operativnog sistema koji izvršava kod. M je povezan sa P i izvršava gorutine iz lokalne ili globalne reda.
Princip rada:
- Nova gorutina se kreira i smešta u lokalnu red dostupnog P.
- M, povezano sa P, uzima gorutinu iz lokalne reda i izvršava je.
- Ako je lokalna red prazan, M pokušava da ukrade gorutine od drugih P.
- Ako P blokira (npr. prilikom sistemskog poziva), povezani M se odvoji, a drugi M se povezuje sa tim P. Blokirani M može biti ponovo korišćen kada sistemski poziv završi.
- Ako je gorutina blokirana na kanalu ili muteksu, ona se stavlja u red čekanja, a planer bira drugu gorutinu za izvršenje na istom M.
- Planer vrši periodične provere za preemptivno prekidanje dugotrajnih gorutina, omogućavajući drugim gorutinama da dobiju vreme za izvršenje.
Tačke preemptivnog prekida (preemption points) javljaju se na određenim mestima:
- Pozivi funkcija/metoda.
- Petlje koje sadrže pozive funkcija.
- Alokacija memorije.
- Sinhronizacioni primitivi (kanali, muteksi).
Primer planiranja:
package main
import (
"fmt"
"runtime"
"time"
)
func worker(id int) {
fmt.Printf("Gorutina %d je počela rad\n", id)
time.Sleep(time.Second) // Simulacija rada
fmt.Printf("Gorutina %d je završila rad\n", id)
}
func main() {
runtime.GOMAXPROCS(2) // Podesavanje broja logičkih procesora
for i := 1; i <= 5; i++ {
go worker(i) // Kreiranje gorutina
}
time.Sleep(3 * time.Second) // Čekanje završetka gorutina
fmt.Println("Glavna gorutina je završena")
}
U ovom primeru, 5 gorutina je planirano na 2 logička procesora. Planer Go će rasporediti ove gorutine između dostupnih niti OS-a koristeći lokalne i moguće globalne redove, kao i mehanizam "krađe" rada (work stealing).
Prednosti ovog pristupa:
- Skalabilnost: Efikasno korišćenje višejadarskih sistema.
- Niski troškovi: Laki gorutini u poređenju sa niti OS-a.
- Jednostavnost korišćenja: Ugrađeno planiranje u jeziku čini paralelno programiranje pristupačnijim.