Green Threads
Green threads are user-space scheduled threads multiplexed over few OS threads, enabling lightweight concurrency — millions of tasks — but requiring cooperative yields and runtime-owned I/O.
Definition
Green threads are scheduled entirely in user space by the runtime or library, not the kernel. Creation is an allocation, not a syscall; context switch is a function call, not a trap. The runtime multiplexes many green threads onto a small pool of OS threads. Blocking kernel operations must be avoided or intercepted, since a blocking green thread pins its carrier.
Context and scope
Go goroutines, Erlang processes, early Java green threads, and Windows fibers. The modern JVM answer is virtual threads; async/await is the callback-shaped alternative to the same problem.
Common misconceptions
- Green threads use all cores — a single-threaded green thread scheduler pins to one core unless the runtime multiplexes onto a thread pool
- Blocking calls work as usual — blocking OS calls freeze the carrier thread and stall every green thread multiplexed on it
- Green threads remove the need for synchronization — shared memory races exist exactly as with OS threads
Anti-patterns
- Calling blocking JDBC or file APIs from goroutine-heavy services and starving the scheduler
- Assuming green thread counts scale linearly with no memory accounting for stacks
- Mixing green thread schedulers with thread-affine native libraries and deadlocking the runtime
Related concepts
Related examples
Authoritative source
What it is
OS threads cost megabytes of stack and a kernel scheduling object each; you can afford thousands, not millions. Green threads shrink both costs into user space: small or growable stacks, and a scheduler that switches contexts in nanoseconds.
How it works
The runtime scheduler maintains runnable queues and multiplexes M green threads onto N OS threads. Yield points are explicit cooperative calls or compiler-inserted checks at function boundaries. I/O must route through runtime-aware non-blocking interfaces so the scheduler parks the green thread, not the carrier.
When to use it
Massive concurrency with blocking-style code readability: many open connections, per-session state machines, pipelines. The runtime owns I/O, which is the price of transparent suspension.
Pitfalls
Blocking into kernel space — a blocking library call pins the carrier and every multiplexed task with it. Preemption granularity varies: Go preempts at function entries and loop backedges; older runtimes never preempt, letting one busy task starve all others. Stack accounting and scheduler tuning become operational work at scale.