Middle
Mi az a futási idő (runtime) és hogyan működik a ütemező (scheduler)?
sobes.tech MI
Válasz az MI-től
A Go futásideje (runtime) a környezet, amelyben a Go programok futnak. Magába foglalja:
- Memóriakezelés: A szemétgyűjtő (garbage collector) automatikusan kezeli a memória kiosztását és felszabadítását.
- Ütemező (scheduler): Kezeli a goroutine-ok végrehajtását az operációs rendszer szálain.
- Rendszerhívások: Interfészt biztosít a rendszerrel való kommunikációhoz.
- Szinkronizációs primitívek: Csatornák, mutexek és más mechanizmusok a goroutine-ok koordinálására.
A Go ütemezője az M:N modellt valósítja meg (sok goroutine sok OS-szálon). Fő komponensei:
- G (Goroutine): Egy könnyű végrehajtási szál, alapvetően egy függvény absztrakciója.
- M (Machine): Egy operációs rendszer szál, amelyen a Go programok futnak.
- P (Processor): Egy logikai processzor, amelyhez egy OS-szál kapcsolódik. Tartalmaz egy helyi
runnablesorozatot goroutine-ok számára.
Az ütemező működési elve:
- Goroutine-ok (G) létrejönnek és hozzáadódnak egy globális vagy helyi
runnablesorhoz. - Az OS-szálak (M) logikai processzorokhoz (P) kapcsolódnak. Az alapértelmezett P száma megegyezik a CPU magok számával (
GOMAXPROCS). - P kiválaszt egy goroutine-t a helyi sorából. Ha a helyi sor üres, P megpróbálja "ellopni" (steal) goroutine-okat más P-k vagy a globális sorból.
- M végrehajtja a goroutine-t.
- Amikor egy goroutine blokkolódik (pl. csatornából olvasás adat nélkül vagy rendszerhívás során), M leválik P-ről, és P elérhetővé válik más goroutine-ok futtatására. A blokkolt goroutine várakozó állapotba kerül. Amikor a blokkolás megszűnik, a goroutine újra
runnablelesz, és visszakerül a sorba. - Ha M rendszerhívásban blokkol, nem tartja P-t. Létrehozható egy új M vagy használható egy meglévő, hogy P folytathassa más goroutine-ok futtatását.
Ez a megközelítés hatékonyan használja ki a processzor erőforrásait, és könnyen skálázható párhuzamos feladatok esetén, miközben elrejti az OS-szálak kezelésének összetettségét a fejlesztő elől.
// Goroutine létrehozásának példája
func myFunc() {
// Goroutine kódja
}
func main() {
go myFunc() // Goroutine indítása
// A fő program párhuzamosan folytatódik
}