Coroutines Basics Quiz

KOTLIN › Concurrency

What best describes what happens when a coroutine hits a suspension point inside a suspend function?

Answer: The coroutine suspends, and the thread is freed for other work

Suspension pauses the coroutine without blocking; the underlying thread is released to do other work and the coroutine resumes later.

Which builder returns a Deferred that you await for a result?

Answer: async

async returns Deferred<T> and you call await() to get the value; launch returns a Job with no result.

Which dispatcher is the correct default choice for CPU-intensive work like parsing or sorting a large list?

Answer: Dispatchers.Default

Dispatchers.Default is backed by a pool sized to the number of CPU cores, intended for CPU-bound work; IO is for blocking I/O.

What is the primary purpose of withContext(Dispatchers.IO) inside a suspend function?

Answer: To switch the block onto an I/O thread, keeping the function main-safe

withContext switches to the specified dispatcher for the block and returns to the original context afterward, so blocking I/O runs off the main thread.

Under the hood, how does the Kotlin compiler implement suspend functions?

Answer: By a CPS transform into a state machine with a hidden Continuation parameter

The compiler rewrites a suspend function using CPS, adding a Continuation parameter and compiling the body into a resumable state machine.

In structured concurrency, what happens to child coroutines when their CoroutineScope is cancelled?

Answer: All child coroutines in that scope are cancelled too

Cancellation propagates down the coroutine hierarchy: cancelling a scope (or its Job) recursively cancels all of its child coroutines.

What is the behavior of Dispatchers.Unconfined?

Answer: It starts in the caller thread, then resumes where suspension decides

Unconfined starts in the caller thread but after the first suspension point resumes on the thread determined by the suspending call; it is an advanced, rarely-needed dispatcher.

How does delay differ from Thread.sleep inside a coroutine?

Answer: delay suspends without blocking, while Thread.sleep blocks the thread

delay is a suspending function that releases the thread while the coroutine waits, whereas Thread.sleep blocks the thread for the whole duration, wasting it.

How does exception delivery differ between launch and async?

Answer: launch propagates to its scope immediately; async holds it for await()

launch treats an uncaught exception as a failure and propagates it up the scope right away, while async stores it in the Deferred so it surfaces when you call await().

What distinguishes supervisorScope from coroutineScope?

Answer: In supervisorScope, one child's failure won't cancel its siblings

supervisorScope uses a SupervisorJob, so a child's failure is isolated and does not cancel its siblings, unlike coroutineScope where one failure cancels the whole scope.

From where can a suspend function be called?

Answer: Only from another suspend function, or inside a coroutine builder

Suspend functions need a continuation, so they can only be invoked from another suspend function or from a coroutine started by a builder like launch, async, or runBlocking.

A coroutine runs a long CPU loop with no suspension points and does not stop when its scope is cancelled. Why?

Answer: Cancellation is cooperative, so an unchecked loop never sees the cancelled state

Cancellation only sets a flag; cooperative code must hit a suspension point or check isActive/ensureActive/yield to actually react, otherwise a tight loop keeps running.

What is the intended use of runBlocking?

Answer: To bridge blocking code to coroutines in main() or tests, blocking the thread

runBlocking blocks the current thread until its body completes, which is useful for main functions and tests but is the wrong tool inside UI code, where it would freeze the thread.

Which statement about Dispatchers.IO is correct in modern kotlinx.coroutines?

Answer: It shares Dispatchers.Default's pool but allows far more concurrent blocking tasks

Dispatchers.IO and Dispatchers.Default draw from the same shared pool; IO allows a large number of concurrent blocking tasks by default, and limitedParallelism can constrain how many run at once.

Back to Coroutines Basics