Kotlin - coroutine yield() what is its purpose?

https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/yield.html

Yields a thread (or thread pool) of the current coroutine dispatcher to other coroutines to run. If the coroutine dispatcher does not have its own thread pool (like Dispatchers.Unconfined) then this function does nothing, but checks if the coroutine Job was completed. This suspending function is cancellable. If the Job of the current coroutine is cancelled or completed when this suspending function is invoked or while this function is waiting for dispatching, it resumes with CancellationException.

It accomplishes at least a few things

  1. It temporarily deprioritises the current long running CPU task, giving other tasks a fair opportunity to run.
  2. Checks whether the current job is cancelled, since otherwise in a tight CPU bound loop, the job may not check until the end.
  3. Allows for progress of child jobs, where there is contention because more jobs than threads. This may be important where the current job should adapt based on progress of other jobs.

After some research, I see that yield is actually from java and the term yielding a thread is what I did not understand.

essentially: yield() basically means that the thread is not doing anything that important and if other threads need to be run, they can run. (I'd prefer to use join as Alex Yu mentioned). Basically, if we want to visualize what yield is doing... whatever thread you call yield on will get pushed to the back of the messaging queue, then other threads with the same priority get executed ahead of it. So it's like going to the back of the line at a club.


In your example, yield() is called inside parent job. It says to your parent: "you work much more, wait please, i will let the other tasks to work for some time, after some time i will let you continue to work ".

Thus parent job waits.. Child job works some time.. After some time, parent job passes the next line which comes after yield(), and cancels the child job.

If you do not use yield() in your example, parent job immediately cancels child job.

Let me explain the yield with different example which shows yield in much more clear way. 2 jobs wait in the queue for waiting thread to let them to work. When you call yield, thread looks into the queue and sees other job waiting so it lets the other job to work.

import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.yield

fun main() = runBlocking {


    val job1 = launch {
        repeat(10) {
            delay(1000)
            println("$it. step done in job 1 ")
            yield()
        }
    }

    val job2 = launch {
        repeat(10) {
            delay(1000)
            println("$it. step done in job 2 ")
            yield()
        }
    }

    job1.join()
    job2.join()
    println("done")
}

Output:

0. step done in job 1 
0. step done in job 2 
1. step done in job 1 
1. step done in job 2 
2. step done in job 1 
2. step done in job 2 
3. step done in job 1 
3. step done in job 2 
4. step done in job 1 
4. step done in job 2 
5. step done in job 1 
5. step done in job 2 
6. step done in job 1 
6. step done in job 2 
7. step done in job 1 
7. step done in job 2 
8. step done in job 1 
8. step done in job 2 
9. step done in job 1 
9. step done in job 2 
done