Difference between runBlocking and coroutineScope

I can’t understand this sentence from the doc:

The main difference between runBlocking and coroutineScope is that the latter does not block the current thread while waiting for all children to complete.

I tried some examples with both functions but the results are the same. Is there any example to understand the difference between them ?

this is the doc link:
https://kotlinlang.org/docs/reference/coroutines/basics.html#scope-builder

2 Likes

It’s hard to create a simple example which demonstrates this. The difference between runBlocking and coroutineScope is the difference between a blocking and a suspending call.

As you might know, you can execute multiple coroutines concurrently on one thread. This is where the power of coroutines originates, as thread creation is resource heavy.
Instead of creating a thread for each part of concurrent code you create a coroutine and run those coroutines in one or possibly multiple threads (at most you create maybe 4 and not 400 threads).

Blocking means that you block the thread. This means no coroutine can execute on this thread until the blocking call is finished.
Suspending on the other hand means, that you just suspend the coroutine. While the coroutine is waiting other coroutines can execute on the thread the coroutine was running on.

10 Likes

Could you answer this question please? @abreslav

You can probably also ask the president. What is wrong with the answer you’ve already got?

I want a code example to show their difference

First, you should be reasonable. Breslav is the head of language development, he does not even responsible for coroutines part. Second, it is not about code, the difference is much deeper, that is what @Wasabi375 tried to explain. The code will look almost the same, but you can’t launch coroutineScope from outside the coroutine and it is strongly discouraged to use runBlocking from inside. So you should either spend some time and read the tutorial or start experimenting.

1 Like

I read the tutorial and I know suspend functions can’t call outside the Coroutine Scope. But when doc explain a difference user should know situations that this difference can affect the result.

What you references is not a tutorial but a very brief documentation. You should read at least something like this if you do not have a background in the problem. There are a lot of articles and tutorials about this out there.
I really do not understand the question. You use the runBlocking on the top level in order to block the thread and create a context for suspend function execution. It does create it’s own scope, but thee scope is rather specific. Then you can create new scopes inside the parent scope. You can’t or at least should not create inner scopes with runBlocking.

2 Likes

I wrote an explanation for this question here:

Maybe it helps you.

3 Likes

Yes I saw that in my first search and it was very useful. I read your answer many times but still I can’t find or make any example to understand their difference in use. I will be grateful if you show me an example.

1 Like

That piece of doc confused me badly as well.

But you can try the following code

import kotlinx.coroutines.*
fun main() = runBlocking {
    val ctx = newSingleThreadContext("MyOwnThread")
    (1..10).forEach {
        launch(ctx) {
            runBlocking {
                delay(500)
                println("foo bar")
            }
        }
    }
}

and replace the runBlocking with coroutineScope to see the differences.

2 Likes

@hui.zhang.jerry that example makes sense, but is there any difference between using runBlocking for the main function and this:

import kotlinx.coroutines.*
suspend fun main() = coroutineScope {
    val ctx = newSingleThreadContext("MyOwnThread")
    (1..10).forEach {
        launch(ctx) {
            coroutineScope {
                delay(500)
                println("foo bar")
            }
        }
    }
}

As far as I can tell in this case they lead to the same result and runBlocking does seem more clear to me, but not sure if there is any underlying difference.

suspend fun main() {}

is just a simple way to write

fun main() = runBlocking {}

So your example is

fun main() = runBlocking { coroutineScope {} }

Also if you try to remove the suspend modifier from the main function your example wouldn’t compile but with runBlocking it does.

Hi @Wasabi375,

suspend fun main() {}

is a language feature, the core library does not include the CoroutineScope, for example you cannot write:

suspend fun main() {
    launch {  } // scope required
}

Instead

fun main() = runBlocking { }

creates a CoroutineScope, and

fun main() = runBlocking { coroutineScope {} }

creates two nested CoroutineScope.


Hi @hui.zhang.jerry,

    launch(ctx) { // new scope
        coroutineScope { // new scope

creates two nested CoroutineScope

suspend fun main() = coroutineScope {

and

fun main() = runBlocking {

are really similar, but runBlocking handles Thread interruption, see https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html

1 Like

I tried another variation of this code to understand the difference better.

fun main() = runBlocking {
    val ctx = newFixedThreadPoolContext(2, "MyOwnThread")
    (1..10).forEach {
        launch(ctx) {
            coroutineScope {
                println("entering foo $it on ${Thread.currentThread().name}")
                delay(500)
                println("exiting foo $it on ${Thread.currentThread().name}")
            }
        }
    }
}

Replace the inner coroutineScope with runBlocking and observe/compare

  1. Which thread enters for $it and which thread exits
  2. Total output
  3. Speed