Sobes.tech
Middle+

Vertel over het patroon voor gelijktijdigheidsbeheer (GMP) in de programmeertaal Go.

sobes.tech AI

Antwoord van AI

GMP is een planningsmodel voor de uitvoering van goroutines in Go, waarbij:

  • G (Goroutine): Een lichtgewicht uitvoeringsdraad, een abstractie boven systeemthreads.
  • M (Machine): Een systeemthread van het OS. Kan de code van één of meerdere goroutines uitvoeren.
  • P (Processor): Een logische processor die een context vertegenwoordigt voor het uitvoeren van goroutines. Aan elke P is een M toegewezen, en P bevat een lokale wachtrij van runnable goroutines. Het standaard aantal P is $GOMAXPROCS (meestal het aantal processor cores).

Werking:

  1. De scheduler (deel van de Go-runtime) plaatst nieuwe goroutines in de globale of lokale wachtrijen van P.
  2. Een M, gekoppeld aan een P, pakt een goroutine uit de wachtrij van P en voert deze uit.
  3. Wanneer een goroutine blokkeert (bijvoorbeeld bij I/O of een mutex):
    • M ontkoppelt zich van de huidige P.
    • De scheduler probeert een andere M te vinden om die P te bezetten, of maakt een nieuwe.
    • De geblokkeerde goroutine wordt in een speciale wachtrij geplaatst.
    • Wanneer de blokkering wordt opgeheven, wordt de goroutine weer runnable en teruggezet in de wachtrij van P.
  4. Wanneer de goroutine haar tijdsquantum verbruikt of expliciet de controle overdraagt (zelden), kan de scheduler M wisselen met een andere goroutine op dezelfde P.

Voordelen:

  • Efficiënt gebruik van systeemthreads M.
  • Vermindering van de overhead bij contextswitches vergeleken met native systeemthreads.
  • Load balancing tussen P via het "work stealing" mechanisme (M kan een goroutine stelen uit de wachtrij van een andere P).

Voorbeeld van het maken van een goroutine:

// main.go
package main

import (
	"fmt"
	"time"
)

func worker(id int) {
	fmt.Printf("Werker %d start\n", id)
	time.Sleep(time.Second) // Illustratie van blokkering/belasting
	fmt.Printf("Werker %d klaar\n", id)
}

func main() {
	for i := 1; i <= 5; i++ {
		go worker(i) // Maak een nieuwe goroutine
	}

	time.Sleep(time.Second * 2) // Wacht tot de goroutines klaar zijn
}