Coroutines
01 / 02

Suspension, Builders & Structured Concurrency

Suspension, Builders & Structured Concurrency

Suspend, Don't Block

A coroutine is a lightweight concurrency unit that suspends and resumes at specific points, letting async code read sequentially without occupying a thread while waiting. A suspended coroutine releases the underlying thread to do other work; a blocked thread stays occupied and idle until the operation finishes — that's the core efficiency advantage.

launch vs. async

scope.launch {
    saveToDatabase(item)  // fire-and-forget, returns a Job
}

val deferred = scope.async {
    fetchUser(id)  // returns Deferred<User>
}
val user = deferred.await()

launch starts a coroutine for its side effects, returning a Job with no result value. async starts a coroutine whose result you need later, returning a Deferred<T> retrieved via .await().

Structured Concurrency & Scope

Coroutines launch within a CoroutineScope, and that scope's lifecycle governs its children — when the scope is cancelled or completes, its coroutines are cancelled too, preventing leaks. This is why coroutine builders require a scope: every coroutine has a clear owner responsible for its cancellation, rather than being launched into an untracked void. GlobalScope.launch bypasses this — a globally-scoped coroutine has no natural owner to cancel it, risking leaks (e.g. work that outlives a destroyed Android Activity).

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free