Search⌘ K
AI Features

A Dispatcher Limited to a Single Thread

Explore how to manage shared state in Kotlin coroutines using dispatchers limited to a single thread. Understand coarse-grained and fine-grained thread confinement techniques and how to use mutex locks with withLock to prevent deadlocks. This lesson guides you through practical methods to ensure safe access to shared resources while balancing performance.

We saw a dispatcher with parallelism limited to a single thread in the “Dispatchers” chapter. This is the easiest solution for most problems with shared states.

package kotlinx.coroutines.app 
import kotlinx.coroutines.*
import java.util.concurrent.Executors

val dispatcher = Dispatchers.IO
    .limitedParallelism(1)

var counter = 0

fun main() = runBlocking {
    massiveRun {
        withContext(dispatcher) {
            counter++
        }
    }
    println(counter) // 1000000
}

suspend fun massiveRun(action: suspend () -> Unit) =
    withContext(Dispatchers.Default) {
        repeat(1000) {
            launch {
                repeat(1000) { action() }
            }
        }
    }
Problem of concurrent use

In practice, we can use this approach in two ways.

Coarse-grained thread confinement

The first approach is known as coarse-grained thread confinement. This is a straightforward approach where we wrap the whole function with withContext, with a dispatcher limited to a single thread. This solution is easy and eliminates conflicts, but the problem is that we lose multithreading capabilities on the whole ...