Middle+
Meséljen a Go nyelvben alkalmazott konkurencia kezelés mintázatáról (GMP).
sobes.tech MI
Válasz az MI-től
A GMP egy ütemezési modell a goroutine-ok végrehajtására Go-ban, ahol:
- G (Goroutine): Egy könnyűsúlyú végrehajtási szál, absztrakció a rendszer szálai felett.
- M (Machine): Egy operációs rendszer szál. Képes egy vagy több goroutine kódját végrehajtani.
- P (Processor): Egy logikai processzor, amely egy kontextust képvisel a goroutine-ok végrehajtásához. Minden P-hez egy M tartozik, és P tartalmaz egy helyi futó goroutine-ok sorát. Az alapértelmezett P száma
$GOMAXPROCS(általában a processzor magjainak száma).
Működése:
- A Go futásideje (runtime) az ütemező új goroutine-okat helyez el a P globális vagy helyi sorába.
- Egy P-hez kapcsolódó M kiválaszt egy goroutine-t a P sorából és végrehajtja.
- Amikor egy goroutine blokkolódik (pl. I/O várakozás vagy mutexnél):
- Az M leválik a jelenlegi P-ről.
- Az ütemező megpróbál egy másik M-t találni, hogy elfoglalja ezt a P-t, vagy újat hoz létre.
- A blokkolt goroutine egy speciális sorba kerül.
- Amikor a blokkolás megszűnik, a goroutine újra futtathatóvá válik és visszakerül a P sorába.
- Amikor a goroutine elfogyasztja az idő kvantumát vagy explicit módon átadja az irányítást (ritkán), az ütemező cserélheti az M-t egy másik goroutine-ra ugyanazon P-n belül.
Előnyei:
- Hatékonyan használja a rendszer szálait M.
- Csökkenti a kontextusváltási költségeket a natív rendszer szálakhoz képest.
- Egyenletes terheléselosztás P-k között a "work stealing" mechanizmus révén (az M ellophat egy goroutine-t egy másik P sorából).
Goroutine létrehozásának példája:
// main.go
package main
import (
"fmt"
"time"
)
func worker(id int) {
fmt.Printf("Munkás %d indítása\n", id)
time.Sleep(time.Second) // Blokkolás/terhelés példája
fmt.Printf("Munkás %d befejezése\n", id)
}
func main() {
for i := 1; i <= 5; i++ {
go worker(i) // Új goroutine létrehozása
}
time.Sleep(time.Second * 2) // Várakozás a goroutine-ok befejezésére
}