How coroutine to be resumend is chosen after suspension of another coroutine

For simplicity suppose that we have 3 coroutines, all running on a single-threaded dispatcher.
If each of them gets suspended - for example calling delay suspending function.
How is next coroutine to be resumed selected? Let’s say there 2 coroutines that are ready to be resumed - which one is selected than? Is there any scheduler which does the coroutine-to-be-resumed selection?

I tried to ilustrate the problem with simple example:

fun main() = runBlocking{
val startTime = System.currentTimeMillis()
	val jobA = launch(CoroutineName("A")) {
    var counter = 1
  		println("${counter}, ${System.currentTimeMillis() - startTime}: $coroutineContext")
    delay(1000)
    counter++
  		println("${counter}, ${System.currentTimeMillis() - startTime}: $coroutineContext")
}
   	val jobB = launch(CoroutineName("B")) {
    val startTime = System.currentTimeMillis()
    var counter = 1
  		println("${counter}, ${System.currentTimeMillis() - startTime}: $coroutineContext")
    delay(2000)
    counter++
  		println("${counter}, ${System.currentTimeMillis() - startTime}: $coroutineContext")
}
val jobC = launch(CoroutineName("C")) {
    var counter = 1
  		println("${counter}, ${System.currentTimeMillis() - startTime}: $coroutineContext")
    delay(2000)
    counter++
  		println("${counter}, ${System.currentTimeMillis() - startTime}: $coroutineContext")
}
}

It gives the following output, however that’s not too informative:

1, 11: [CoroutineName(A), CoroutineId(2), "A#2":StandaloneCoroutine{Active}@15615099, BlockingEventLoop@1edf1c96]
1, 0: [CoroutineName(B), CoroutineId(3), "B#3":StandaloneCoroutine{Active}@53bd815b, BlockingEventLoop@1edf1c96]
1, 22: [CoroutineName(C), CoroutineId(4), "C#4":StandaloneCoroutine{Active}@2401f4c3, BlockingEventLoop@1edf1c96]
2, 1020: [CoroutineName(A), CoroutineId(2), "A#2":StandaloneCoroutine{Active}@15615099, BlockingEventLoop@1edf1c96]
2, 2001: [CoroutineName(B), CoroutineId(3), "B#3":StandaloneCoroutine{Active}@53bd815b, BlockingEventLoop@1edf1c96]
2, 2023: [CoroutineName(C), CoroutineId(4), "C#4":StandaloneCoroutine{Active}@2401f4c3, BlockingEventLoop@1edf1c96]

This behavior is undefined, it depends by the specific implementation of the actual Dispatcher and it subject to change.

1 Like

Thank you!

Although, given that the Dispatcher has no special knowledge about the coroutines that are ready to resume, I think first-come-first-served is the only reasonable choice.

1 Like

You can consider dispatchers mostly FIFO, but a pure FIFO is applicable only on a single thread (like event loop).

1 Like