Coroutine synchronization

Kotlin provides a thread non-blocking features to synchronize coroutoines.

Mutex protects all modifications of the shared state with a critical section that is never executed concurrently. Mutex has two states: locked and unlocked. It is non-reentrant, that is invoking lock even from the same thread/coroutine that currently holds the lock still suspends the invoker.

Semaphore limits the number of coroutines that can execute specified code at the same time. Semaphore with permits = 1 is essentially a Mutex.

Mutex similar to the synchronize keyword and ReentrantLock class in Java. Semaphore is similar to the java.util.concurrent.Semaphore in Java.

Mutex usage example
// using a mutex will be faster than using the AtomicInteger class
val mutex = Mutex()
var counter = 0

fun main() = runBlocking {
    withContext(Dispatchers.Default) {
        massiveRun {
            // protect each increment with lock
            mutex.withLock {
                counter++
            }
        }
    }
    println("Counter = $counter")
}
Semaphore usage example
val requestSemaphore = Semaphore(5)

val futures = mDownloadJobs.map {
    async {
        // Will limit number of concurrent requests to 5
        requestSemaphore.withPermit {
            it.loadData()
        }
    }
}

val responses = futures.awaitAll()
Sequential execution
// Sequential execution of incoming blocks
// which can be passed from different coroutines
class QueueExecutor  {
    private val mutex: Mutex = Mutex()

    suspend fun <T> enqueue(block: suspend () -> T): T {
        mutex.withLock {
            return block()
        }
    }
}