liveBook · Manning

Coroutine

As explained in Kotlin in Action, 2E

A coroutine is a lightweight suspendable computation that can pause its execution and resume it later without blocking its underlying thread.

A coroutine is an instance of a suspendable computation: code that can pause while waiting and resume later without blocking its underlying thread. It is useful when an application must keep handling UI work, requests, or other tasks while network or I/O operations are pending. Coroutines are lightweight abstractions that run on JVM threads, so they support concurrent work without treating a thread as the unit of every short-lived task. section 14.0 section 14.3

Keep sequential logic non-blocking

Mark operations that may wait with suspend, then call them in normal top-to-bottom order. While login or loading data is suspended, the thread can perform other work instead of freezing a UI or wasting a request-handling thread. This readable shape is the practical advantage: asynchronous work does not force callback nesting or wrapped future return types. section 14.4.1 section 14.5

suspend fun processUser(credentials: Credentials) {
    val user = authenticate(credentials)                       #1
    val data = loadUserData(user)                              #2
    val profilePicture = loadImage(data.imageID)               #3
    // ...
}
 
suspend fun authenticate(c: Credentials): User { /* ... */ }   #4
suspend fun loadUserData(u: User): Data { /* ... */ }
suspend fun loadImage(id: Int): Image { /* ... */ }

The three calls read as ordinary sequential code, but each suspending operation may pause without blocking the thread. section 1.2.4

A suspending function is the core primitive. It may call another suspending function, but it must itself be called from a suspending function or from a coroutine. A coroutine supplies the machinery that lets its body suspend. Coroutine builders create these computations: use launch for work with no returned value, async for an asynchronously computed value, and runBlocking to bridge blocking code and suspending functions. section 14.6 section 14.9

suspend fun loadAndOverlay(first: String, second: String): Image =
    coroutineScope {
        val firstDeferred = async { loadImage(first) }                  #1
        val secondDeferred = async { loadImage(second) }                #2
        combineImages(firstDeferred.await(), secondDeferred.await())    #3
    }

async starts two image loads from one scope; await obtains both results before combining them. section 1.2.4

Coroutines are not merely renamed threads. Threads are comparatively expensive system resources and do not inherently form a task hierarchy. Structured concurrency gives coroutine work parent-child relationships for lifecycle management, cancellation, and errors. With ordinary non-supervisor parents, an uncaught failure in one child completes the parent exceptionally, cancels sibling children, and propagates the exception upward. This avoids continuing work that can no longer produce the shared result. section 14.3 section 18.2.1

Choose coroutines when the work benefits from these properties:

  • Suspend during network requests or I/O so the underlying thread remains available for other work. section 14.3
  • Keep dependent asynchronous steps in direct sequential-looking code rather than nested callbacks or chains of operators. section 14.4.1 section 14.5
  • Start related concurrent tasks from a common scope so their lifetime, cancellation, and failures can be managed together. section 1.2.4 section 18.2.1

Coroutine support in the language and standard library is intentionally small; most higher-level APIs come from kotlinx.coroutines. Dispatchers select the thread or pool on which a coroutine runs, and multithreaded dispatchers require care when multiple coroutines modify shared data in parallel. Coroutines can provide concurrency and can also use the parallelism supplied by their underlying threads. section 14.6 section 14.9

How Kotlin in Action, 2E covers it

How deep it goes
Explains suspension, builders, thread relationships, dispatchers, and failure propagation; defers deeper suspension mechanics and structured concurrency treatment.
Examples
Uses sequential login and user-data loading, concurrent image overlaying, and a failing sibling beside a heartbeat coroutine.
What it assumes
Builds from familiar blocking functions and threads, then introduces suspending functions before defining coroutine builders.
What you can do after
Apply it via kotlinx.coroutines builders and suspending functions to write non-blocking sequential-looking concurrent code.
How it connects
Connects suspending functions, structured concurrency, threads, dispatchers, callbacks, futures, reactive streams, and cancellation.

Also explained in

Compare how 8 books explain coroutine →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Kotlin in Action, 2E. The section links point to the parts of the book it draws on.