Middle+
Fale sobre o padrão de gestão de concorrência (GMP) na linguagem Go.
sobes.tech IA
Resposta da IA
O GMP é um modelo de planeamento da execução de goroutines em Go, onde:
- G (Goroutine): Um fio de execução leve, uma abstração sobre os fios do sistema.
- M (Machine): Um fio do sistema operativo. Pode executar o código de uma ou várias goroutines.
- P (Processor): Um processador lógico, que representa um contexto para a execução de goroutines. A cada P é atribuído um M, e P contém uma fila local de goroutines em estado runnable. O número de P por defeito é
$GOMAXPROCS(geralmente o número de núcleos do processador).
Funciona assim:
- O agendador (parte do runtime de Go) coloca novas goroutines nas filas globais ou locais de P.
- Um M, associado a um P, retira uma goroutine da fila de P e a executa.
- Quando uma goroutine fica bloqueada (por exemplo, à espera de I/O ou num mutex):
- O M desliga-se do P atual.
- O agendador tenta encontrar outro M para ocupar esse P, ou cria um novo.
- A goroutine bloqueada é colocada numa fila especial.
- Quando o bloqueio é libertado, a goroutine volta a ficar em estado runnable e regressa à fila de P.
- Quando a goroutine esgota o seu quantum de tempo ou cede explicitamente o controlo (raramente), o agendador pode trocar o M por outra goroutine no mesmo P.
Vantagens deste método:
- Uso eficiente dos fios do sistema M.
- Redução dos custos de mudança de contexto em comparação com os fios nativos do sistema operativo.
- Balanceamento de carga entre P através do mecanismo de "work stealing" (M pode roubar uma goroutine da fila de outro P).
Exemplo de criação de uma goroutine:
// main.go
package main
import (
"fmt"
"time"
)
func worker(id int) {
fmt.Printf("Worker %d a iniciar\n", id)
time.Sleep(time.Second) // Ilustração de bloqueio/ocupação
fmt.Printf("Worker %d terminado\n", id)
}
func main() {
for i := 1; i <= 5; i++ {
go worker(i) // Criar uma nova goroutine
}
time.Sleep(time.Second * 2) // Esperar que as goroutines terminem
}