Middle+
Parlez du modèle de gestion de la concurrence (GMP) dans le langage Go.
sobes.tech IA
Réponse de l'IA
GMP est un modèle de planification de l'exécution des goroutines en Go, où :
- G (Goroutine) : Un fil d'exécution léger, une abstraction au-dessus des threads système.
- M (Machine) : Un thread du système d'exploitation. Peut exécuter le code d'une ou plusieurs goroutines.
- P (Processor) : Un processeur logique, représentant un contexte pour l'exécution des goroutines. À chaque P est assigné un M, et P contient une file d'attente locale de goroutines en état runnable. Le nombre de P par défaut est
$GOMAXPROCS(généralement le nombre de cœurs du processeur).
Fonctionnement :
- Le planificateur (partie du runtime de Go) place de nouvelles goroutines dans les files d'attente globales ou locales de P.
- Un M, associé à un P, prend une goroutine de la file d'attente de P et l'exécute.
- Lorsqu'une goroutine se bloque (par exemple, en attendant une opération I/O ou un mutex) :
- Le M se détache du P actuel.
- Le planificateur tente de trouver un autre M pour occuper ce P, ou en crée un nouveau.
- La goroutine bloquée est placée dans une file d'attente spéciale.
- Lorsqu'elle est débloquée, la goroutine redevient runnable et retourne dans la file d'attente de P.
- Lorsqu'une goroutine épuise son quantum de temps ou cède explicitement le contrôle (rarement), le planificateur peut changer le M pour une autre goroutine dans le même P.
Avantages :
- Utilisation efficace des threads M du système.
- Réduction des coûts de changement de contexte par rapport aux threads natifs du système d'exploitation.
- Équilibrage de la charge entre P grâce au mécanisme de "work stealing" (M peut voler une goroutine de la file d'un autre P).
Exemple de création d'une goroutine :
// main.go
package main
import (
"fmt"
"time"
)
func worker(id int) {
fmt.Printf("Travailleur %d démarrant\n", id)
time.Sleep(time.Second) // Illustration du blocage/occupation
fmt.Printf("Travailleur %d terminé\n", id)
}
func main() {
for i := 1; i <= 5; i++ {
go worker(i) // Créer une nouvelle goroutine
}
time.Sleep(time.Second * 2) // Attendre la fin des goroutines
}