Mutex and Semaphore for Shared State
Protect shared mutable state using Mutex and limit concurrency with Semaphore.
The Shared State Problem
Coroutines on multiple threads can corrupt shared mutable state. Without synchronization, concurrent increments produce wrong results.
import kotlinx.coroutines.*
fun main() = runBlocking {
var counter = 0
val jobs = List(1000) {
launch(Dispatchers.Default) { counter++ } // race condition!
}
jobs.forEach { it.join() }
println("Expected 1000, got: $counter") // likely wrong
}Mutex Basics
Mutex is a mutual exclusion lock for coroutines. It suspends (not blocks) the caller until the lock is available.
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
fun main() = runBlocking {
val mutex = Mutex()
var counter = 0
val jobs = List(1000) {
launch(Dispatchers.Default) {
mutex.withLock { counter++ } // safe
}
}
jobs.forEach { it.join() }
println("Counter: $counter") // 1000
}All lessons in this course
- Channel Basics: send, receive, and close
- Channel Types: Rendezvous, Buffered, Conflated, Unlimited
- Mutex and Semaphore for Shared State
- Actors and Structured State Management