Sobes.tech
Middle+

Povedzte o vzorec riadenia konkurencie (GMP) v jazyku Go.

sobes.tech AI

Odpoveď od AI

GMP je model plánovania vykonávania goroutines v Go, kde:

  • G (Goroutine): Ľahký vlákno na vykonávanie, abstrakcia nad systémovými vláknami.
  • M (Machine): Vlákno operačného systému. Môže vykonávať kód jednej alebo viacerých goroutines.
  • P (Processor): Logický procesor, ktorý predstavuje kontext na vykonávanie goroutines. Každému P je pridelené M a P obsahuje lokálnu frontu runnable goroutines. Počet P je predvolený na $GOMAXPROCS (zvyčajne počet jadier procesora).

Ako to funguje:

  1. Plánovač (časť runtime Go) umiestňuje nové goroutines do globálnych alebo lokálnych front P.
  2. M, spojené s P, vezme goroutine z fronty P a vykoná ju.
  3. Keď goroutine zablokuje (napríklad pri čakaní na I/O alebo na mutexe):
    • M sa odpojí od aktuálneho P.
    • Plánovač sa pokúsi nájsť iné M, ktoré obsadí P, alebo vytvorí nové.
    • Zablokovaná goroutine sa umiestni do špeciálnej fronty.
    • Keď sa blokovanie odstráni, goroutine sa stáva znova runnable a vráti sa do fronty P.
  4. Keď goroutine vyčerpá svoj kvant času alebo explicitne odovzdá kontrolu (zriedka), plánovač môže zmeniť M na inú goroutine v tom istom P.

Výhody:

  • Efektívne využívanie systémových vlákien M.
  • Zníženie nákladov na prepínanie kontextu v porovnaní s natívnymi systémovými vláknami.
  • Vyvažovanie záťaže medzi P pomocou mechanizmu "work stealing" (M môže ukradnúť goroutine z fronty iného P).

Príklad vytvorenia goroutine:

// main.go
package main

import (
	"fmt"
	"time"
)

func worker(id int) {
	fmt.Printf("Pracovník %d začína\n", id)
	time.Sleep(time.Second) // Ilustrácia blokovania/záťaže
	fmt.Printf("Pracovník %d končí\n", id)
}

func main() {
	for i := 1; i <= 5; i++ {
		go worker(i) // Vytvorenie novej goroutine
	}

	time.Sleep(time.Second * 2) // Čakanie na ukončenie goroutine
}