| Builder | Returns | Blocks OS thread | Waits completion | New Job | Root Job | New coroutine | Root coroutine | Suspend point |
|---|---|---|---|---|---|---|---|---|
| runBlocking { } (plug, rarely used) |
block result | ✓ Yes | ✓ Yes | ✓ Yes | ✓ Yes | ✓ Yes | ✓ Yes CEH doesn't work | ✗ No |
| withContext(Dispatcher...) { } | runInterruptible { } |
block result | ✗ No | ✓ Yes | ✗ No | — | ✗ No | — | ✓ Yes |
| coroutineScope { } | block result | ✗ No | ✓ Yes | ✓ Yes | ✗ No | ✓ Yes | ✗ No | ✓ Yes |
| supervisorScope { } | block result | ✗ No | ✓ Yes | ✓ Yes SupervisorJob | ✗ No | ✓ Yes |
✗ No
CEH works for children |
✓ Yes |
| GlobalScope. ... { } (e.g., GlobalScope.launch { }) |
Job/Deffered | ✗ No | ✗ No | ✓ Yes | ✓ Yes | ✓ Yes | ✓ Yes | ✗ No |
| launch { } / async { } | Job/Deffered | ✗ No | ✗ No | ✓ Yes | ✗ No | ✓ Yes | ✗ No | ✗ No |
|
launch(Job()) { } / async(Job()) { }
⚠️ anti-pattern
breaks structured concurrency
|
Job/Deffered | ✗ No | ✗ No | ✓ Yes | ✓ Yes | ✓ Yes |
✓ Yes
passed Job() becomes root
CEH works for launch, NOT for async |
✗ No |
| Expression | Returns | Blocks thread | Waits completion | New Job | Root Job | New coroutine | Root coroutine | Suspend point |
|---|---|---|---|---|---|---|---|---|
| val my = CoroutineScope() | CoroutineScope(Job()) | CoroutineScope(SupervisorJob()) |
itself | ✗ No | ✗ No | ✓ Yes | ✓ Yes gets/creates root | ✗ No | — | ✗ No |