4
votes

Kotlin's runBlocking Coroutine is supposed to block the current thread until the Coroutine inside the block completes execution but it doesn't seem to be doing so when the Coroutine inside the block is GlobalScope.launch

I am trying to understand how Kotlin's Coroutines work and reading the documentation here - https://kotlinlang.org/docs/reference/coroutines/basics.html

In the example -

fun main() = runBlocking<Unit> { // start main coroutine
    GlobalScope.launch { // launch new coroutine in background and continue
        delay(1000L)
        println("World!")
    }
    println("Hello,") // main coroutine continues here immediately
    delay(2000L)      // delaying for 2 seconds to keep JVM alive
}

It is mentioned that "The main thread, that invokes runBlocking, blocks until the coroutine inside runBlocking completes". If this is so then why do we need the two second delay to block the main thread at the end of the runBlocking? Why doesn't runBlocking doesn't block the main thread until the GlobalScope.launch completes?

However the following inner runBlocking blocks main thread until the delay function completes. What's the difference here? Why doesn't runBlocking in the above block main thread until GlobalScope.launch completes in a similar way-

fun main(){ // start main coroutine
    GlobalScope.launch { // launch new coroutine in background and continue
        delay(1000L)
        println("World!")
    }
    println("Hello,") // main coroutine continues here immediately
    runBlocking{
     delay(2000L)      // delaying for 2 seconds to keep JVM alive
    }
}

I expect that when the main function is wrapped in a runBlocking co-routine, the main thread should be blocked until GlobalScope.launch completes its execution.

1
I figured out the answer! It looks like the Coroutine launched by GlobalScope.launch runs in the Global Scope and the main coroutine doesn't wait until it is done because it is not launched in its scope. If GlobalScope.launch is changed to simply launch then the Coroutine will be launched within the scope of the main coroutine and as such the main thread will be blocked until its completion.cubsnlinux
GlobalScope.launch { }.join() or async{ }.await() stackoverflow.com/a/48079738/10259099Rofie Sagara

1 Answers

3
votes

A coroutine in a scope will block until all it's children (jobs) in the same scope will have finished. However explicitely launching coroutines in another scope will not make them real children, and therefore they are not awaited.

This article also provides a bit of information around this particular case: https://medium.com/@elizarov/the-reason-to-avoid-globalscope-835337445abc