Coroutines
Coroutines are functions whose execution can be suspended and resumed, letting many logical tasks share one thread cooperatively instead of one thread per task.
Definition
A coroutine is a generalised subroutine that can pause at suspension points, yielding control to a scheduler and later resuming from the same logical position with its local state preserved.
Context and scope
They underpin async and await, generators, and Go and Kotlin concurrency models that multiplex many tasks onto few operating-system threads.
Common misconceptions
- coroutines run in parallel on multiple CPU cores by definition
- a suspended coroutine keeps an operating-system thread blocked
Anti-patterns
- calling blocking code inside a coroutine and stalling the scheduler
- treating coroutine-local state as if it were thread-local
Related concepts
Related examples
Authoritative source
Definition
A coroutine is a generalised subroutine that can pause at suspension points, yielding control to a scheduler and later resuming from the same logical position with its local state preserved.
They underpin async and await, generators, and Go and Kotlin concurrency models that multiplex many tasks onto few operating-system threads. Compared to simpler alternatives, this concept fits best when the trade-off it represents is the one the system actually cares about.
When to use it
A common use case is applying it at the boundary where the cost of getting it wrong is highest, and the scenario usually involves a concrete guarantee the system must uphold. Unlike an ad hoc approach, it makes that guarantee explicit, reviewable, and testable.
How it works
When a coroutine awaits, it unwinds to its caller and the underlying thread is free to run other work, so thousands of tasks can be in flight without thousands of threads.
Parallelism is a separate concern achieved by running tasks on a pool of threads or processors, so concurrency and parallelism are not the same thing.
Trade-offs and alternatives
Because a coroutine may resume on a different thread, any mutable state shared across suspension points needs synchronisation just as in threaded code. The main drawback is the extra complexity it introduces, so the benefit should clearly outweigh that cost before a team adopts it.
Common misconceptions
A persistent misconception is that coroutines run in parallel on multiple CPU cores by definition. Another is that a suspended coroutine keeps an operating-system thread blocked. For example, an engineer who assumes otherwise may design around a guarantee that does not actually exist, which only becomes obvious under load or failure.
Anti-patterns to avoid
Two recurring anti-patterns are to calling blocking code inside a coroutine and stalling the scheduler and to treating coroutine-local state as if it were thread-local. Both tend to surface as hard-to-debug production issues rather than obvious test failures. Related concepts include Software Transactional Memory, Happens-Before Relationship, Thread-Local Storage.