Under The Hood
backend go Go 1.21+ (preemption improvements in 1.14+)

Go scheduler: GMP model

Last updated
Prerequisites:
Go goroutines and channels basics
Understanding of OS threads vs user-space scheduling
  • go
  • goroutine
  • scheduler
  • gmp
  • concurrency
  • runtime

Read at your depth

The practical view

go func() { ... }() starts a goroutine. Goroutines are lightweight user-space threads: they start with a tiny stack (2KB, grows) and are multiplexed by the Go runtime onto a small set of OS threads. The runtime scheduler uses the GMP model: G is a goroutine, M is an OS thread (machine), P is a processor (logical CPU, default GOMAXPROCS = number of cores). A goroutine blocks on a channel/syscall; the runtime parks its M or the G and schedules another G. You do not manage threads; the runtime balances work across Ps.

Legacy vs modern

Blocking the main thread vs goroutine-parallel work

Serialized sequential work leaves cores idle; distributing across goroutines uses GOMAXPROCS workers through the GMP scheduler.

before → after
Sequential work
var total int64
for _, n := range nums {
  total += heavy(n) // one core does everything
}
Worker-pool parallelism
jobs := make(chan int); results := make(chan int64)
// N workers consume jobs; the GMP scheduler keeps all Ps busy

Interview gotchas

Under The Hood — a multi-depth technical interview hub.

Press ⌘ K to search.