...

/

Structured Concurrency

Structured Concurrency

Learn about structured concurrency in coroutine builders.

We'll cover the following...

If we start a coroutine on GlobalScope, the program won’t wait for it. As previously mentioned, coroutines do not block any threads, and nothing prevents the program from ending. This is why, in the example below, we need to call an additional delay at the end of runBlocking if we want to see “World!” printed.

package kotlinx.coroutines.app
import kotlinx.coroutines.*

fun main() = runBlocking {
   GlobalScope.launch {
       delay(1000L)
       println("World 1!")
   }
   GlobalScope.launch {
       delay(2000L)
       println("World 2!")
   }
   println("Hello,")
   delay(3000L)
}
Call an additional delay at the end of runBlocking

Why do we need GlobalScope in the first place? We need it because launch and async are extension functions on the CoroutineScope. However, if we look at these definitions and runBlocking, we’ll see that the block parameter is a function type whose receiver type is also CoroutineScope.

Press + to interact
fun <T> runBlocking(
context: CoroutineContext = EmptyCoroutineContext,
block: suspend CoroutineScope.() -> T
): T
fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job
fun <T> CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T>

This means that we can get rid of the GlobalScope. Instead, launch can be ...