Bird
Raised Fist0
Kotlinprogramming~20 mins

Why structured concurrency prevents leaks in Kotlin - Challenge Your Understanding

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Structured Concurrency Mastery
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Output of coroutine scope with structured concurrency
What is the output of this Kotlin code using structured concurrency?
Kotlin
import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        delay(100)
        println("Task 1 done")
    }
    launch {
        delay(50)
        println("Task 2 done")
    }
    println("Main done")
}
AMain done\nTask 2 done\nTask 1 done
BMain done
CTask 1 done\nTask 2 done\nMain done
DTask 2 done\nTask 1 done
Attempts:
2 left
💡 Hint
Remember that runBlocking waits for all launched coroutines inside it to complete before finishing.
🧠 Conceptual
intermediate
1:30remaining
Why does structured concurrency prevent coroutine leaks?
Which statement best explains why structured concurrency prevents coroutine leaks in Kotlin?
ABecause Kotlin coroutines use garbage collection to clean up leaked coroutines.
BBecause coroutines run on a single thread and cannot leak resources.
CBecause coroutines automatically restart if they fail, preventing leaks.
DBecause all child coroutines are tied to a parent scope and must complete or cancel before the parent finishes.
Attempts:
2 left
💡 Hint
Think about how coroutine lifecycles are managed in structured concurrency.
🔧 Debug
advanced
2:00remaining
Identify the leak caused by missing coroutine scope
What error or problem occurs when launching a coroutine without a proper parent scope in Kotlin?
Kotlin
import kotlinx.coroutines.*

fun main() {
    GlobalScope.launch {
        delay(1000)
        println("Leaked coroutine finished")
    }
    println("Main finished")
}
AThe coroutine will throw a CancellationException immediately.
BThe program will not compile due to missing coroutine scope.
CThe coroutine may continue running after main ends, causing a resource leak.
DThe coroutine will block the main thread until it finishes.
Attempts:
2 left
💡 Hint
Consider what happens when coroutines are launched in GlobalScope.
📝 Syntax
advanced
2:00remaining
Correct syntax for structured concurrency with coroutineScope
Which option correctly uses structured concurrency to launch two child coroutines and waits for both to finish?
Kotlin
import kotlinx.coroutines.*

suspend fun doWork() = coroutineScope {
    // launch two child coroutines here
}
ArunBlocking { launch { println("Child 1") } }
B
launch { delay(100); println("Child 1") }
launch { delay(200); println("Child 2") }
C
async { println("Child 1") }
async { println("Child 2") }
D
GlobalScope.launch { println("Child 1") }
GlobalScope.launch { println("Child 2") }
Attempts:
2 left
💡 Hint
Inside coroutineScope, use launch to start child coroutines tied to the scope.
🚀 Application
expert
2:30remaining
How structured concurrency handles exceptions to prevent leaks
Given this code, what happens when one child coroutine throws an exception inside coroutineScope?
Kotlin
import kotlinx.coroutines.*

suspend fun main() = coroutineScope {
    launch {
        delay(100)
        throw RuntimeException("Error in child 1")
    }
    launch {
        delay(200)
        println("Child 2 finished")
    }
}
AThe exception cancels the entire coroutineScope, so Child 2 is cancelled and "Child 2 finished" is not printed.
BThe exception is ignored, and Child 2 runs to completion printing "Child 2 finished".
CThe exception crashes the program immediately without cancelling Child 2.
DThe exception is caught automatically and printed, but both children complete.
Attempts:
2 left
💡 Hint
Think about how coroutineScope handles exceptions from child coroutines.

Practice

(1/5)
1. What is the main reason structured concurrency helps prevent resource leaks in Kotlin?
easy
A. It requires manual task cancellation by the programmer.
B. It automatically frees memory after each line of code.
C. It disables background tasks after 5 seconds.
D. It ensures all tasks start and finish together, avoiding orphaned tasks.

Solution

  1. Step 1: Understand structured concurrency concept

    Structured concurrency groups related tasks so they start and finish as a unit.
  2. Step 2: Link grouping to resource management

    This grouping prevents tasks from running forever and leaking resources by ensuring no orphaned tasks remain.
  3. Final Answer:

    It ensures all tasks start and finish together, avoiding orphaned tasks. -> Option D
  4. Quick Check:

    Grouping tasks = prevents leaks [OK]
Hint: Think: tasks grouped start and end together [OK]
Common Mistakes:
  • Confusing automatic memory freeing with concurrency
  • Believing tasks stop after fixed time automatically
  • Assuming manual cancellation is always required
2. Which Kotlin syntax correctly starts a structured concurrency block using coroutineScope?
easy
A. launch { coroutineScope { /* task */ } }
B. coroutineScope() -> launch { /* task */ }
C. coroutineScope { launch { /* task */ } }
D. launch coroutineScope { /* task */ }

Solution

  1. Step 1: Recall coroutineScope usage

    In Kotlin, coroutineScope is a suspending function that takes a lambda block where child coroutines run.
  2. Step 2: Identify correct syntax

    The correct syntax is coroutineScope { launch { /* task */ } } which starts a structured block with a child coroutine.
  3. Final Answer:

    coroutineScope { launch { /* task */ } } -> Option C
  4. Quick Check:

    coroutineScope with lambda block = coroutineScope { launch { /* task */ } } [OK]
Hint: coroutineScope takes a lambda block with launch inside [OK]
Common Mistakes:
  • Using parentheses incorrectly with coroutineScope
  • Placing launch outside coroutineScope block
  • Omitting braces for lambda block
3. What will be the output of this Kotlin code snippet?
runBlocking {
  launch {
    delay(100)
    println("Task done")
  }
  println("Start")
}
medium
A. Start
B. Start\nTask done
C. Task done\nStart
D. No output

Solution

  1. Step 1: Analyze runBlocking and launch behavior

    runBlocking blocks the main thread until all child coroutines complete. The launch coroutine delays 100ms before printing.
  2. Step 2: Trace output order

    "Start" prints immediately, then after 100ms delay, "Task done" prints. So output is "Start" then "Task done".
  3. Final Answer:

    Start\nTask done -> Option B
  4. Quick Check:

    runBlocking waits, launch delays, prints after Start [OK]
Hint: runBlocking waits for launch; delay prints after Start [OK]
Common Mistakes:
  • Assuming launch runs before println("Start")
  • Thinking delay blocks main thread
  • Expecting no output due to delay
4. Identify the error in this Kotlin code that breaks structured concurrency:
fun main() = runBlocking {
  GlobalScope.launch {
    delay(1000)
    println("Leaked task")
  }
  println("Main done")
}
medium
A. Using GlobalScope.launch causes the task to run outside structured concurrency.
B. Missing delay before println("Main done").
C. runBlocking cannot be used with launch.
D. println("Leaked task") is outside coroutine scope.

Solution

  1. Step 1: Understand GlobalScope effect

    GlobalScope.launch starts a coroutine not tied to the current scope, so it can outlive runBlocking.
  2. Step 2: Link to structured concurrency principles

    This breaks structured concurrency because the launched task can leak and run after main finishes, causing resource leaks.
  3. Final Answer:

    Using GlobalScope.launch causes the task to run outside structured concurrency. -> Option A
  4. Quick Check:

    GlobalScope.launch breaks structured concurrency [OK]
Hint: GlobalScope.launch runs outside structured concurrency [OK]
Common Mistakes:
  • Thinking delay is required before printing main done
  • Believing runBlocking disallows launch
  • Misunderstanding println placement
5. You want to run multiple tasks concurrently but ensure none leak after completion. Which Kotlin approach best applies structured concurrency to prevent leaks?
hard
A. Use coroutineScope or supervisorScope to launch child coroutines inside a suspending block.
B. Launch all tasks with GlobalScope.launch and manually cancel them later.
C. Run tasks sequentially without coroutines to avoid leaks.
D. Use runBlocking only for all tasks without launching coroutines.

Solution

  1. Step 1: Identify structured concurrency tools

    coroutineScope and supervisorScope provide structured concurrency by grouping child coroutines and waiting for their completion.
  2. Step 2: Compare with other options

    GlobalScope.launch risks leaks, sequential runs lose concurrency benefits, and runBlocking alone doesn't manage child coroutines properly.
  3. Final Answer:

    Use coroutineScope or supervisorScope to launch child coroutines inside a suspending block. -> Option A
  4. Quick Check:

    coroutineScope groups tasks safely [OK]
Hint: Use coroutineScope or supervisorScope for safe concurrency [OK]
Common Mistakes:
  • Relying on GlobalScope.launch without cancellation
  • Avoiding concurrency to prevent leaks
  • Misusing runBlocking without child coroutines
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard