What is the order of execution with coroutines?

元气小坏坏 提交于 2019-12-11 16:48:18

问题


Consider the following code in kotlin.

val scope = CoroutineScope(Dispatchers.Main + Job())
scope.launch {
   println("inside coroutine")
}
println("outside coroutine")

We create a coroutine in the Main(UI) thread and there is some code after the coroutine.
I know it doesn´t make much sense to do that in real code, but it´s just a theoretical question.

Considering that the coroutine runs in the Main thread, why println("outside coroutine") is ALWAYS executed first?
I would have expected that sometimes i would see first outside coroutine and other times, first inside coroutine, kind of like two threads.
Who (OS or Coroutines implementation) decides that the coe outside the coroutine is run first?


回答1:


Considering that the coroutine runs in the Main thread, why println("outside coroutine") is ALWAYS executed first?

Let's imagine that your code instead was this:

someView.post {
   println("inside post")
}
println("outside post")

Here, we create a Runnable (lambda expression) and pass that to post() on some View. post() says that the Runnable will be run() on the main application thread... eventually. That Runnable is put on the work queue that the Looper powering the main application thread uses, and it gets executed when that Runnable gets to the top of the queue (more or less — the details are messier IIRC but not important here).

But if you are executing this code on the main application thread, println("outside post") will always be printed first. The Runnable is placed onto the queue to be executed later, but you are still executing on the main application thread, and so even if the queue were empty, that Runnable will not run until you return control of the main application thread back to Android. So, after the call to post(), execution continues with println("outside post").

Under the covers, Dispatchers.Main is basically using post() (again, the details are more complicated but not too important for this discussion). So, when you launch() the coroutine, that lambda expression gets queued up to be executed eventually on the main application. But, you are already on the main application thread, so execution continues normally, and the println("outside post") gets printed before the coroutine gets a chance to do anything.

Suppose that your code instead was:

val scope = CoroutineScope(Dispatchers.Main + Job())
scope.launch {
   println("inside coroutine")
}
scope.launch {
   println("inside another coroutine")
}

Now you are in a situation where in theory either of those lines could be printed first. You are queuing up both lambda expressions, and it is up to the dispatcher to decide what to run on what thread at what point. In practice, it would not surprise me if "inside coroutine" is always printed first, as a simple implementation of Dispatchers.Main would use FIFO ordering in the absence of other constraints (e.g., a coroutine is blocked on I/O). However, you should not assume a particular order of invocation of those two coroutines.



来源:https://stackoverflow.com/questions/58442006/what-is-the-order-of-execution-with-coroutines

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!