Coroutine Mutex and Synchronization
Synchronize shared mutable state in coroutines with Mutex, atomic operations, and thread confinement.
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.util.concurrent.atomic.AtomicInteger
fun main() = runBlocking {
// Problem: shared mutable state without sync
var unsafeCounter = 0
coroutineScope {
repeat(1000) {
launch(Dispatchers.Default) { repeat(100) { unsafeCounter++ } }
}
}
println("Unsafe: $unsafeCounter") // likely < 100000
// Solution 1: Mutex
var mutexCounter = 0
val mutex = Mutex()
coroutineScope {
repeat(1000) {
launch(Dispatchers.Default) {
repeat(100) { mutex.withLock { mutexCounter++ } }
}
}
}
println("Mutex: $mutexCounter") // exactly 100000
// Solution 2: AtomicInteger
val atomicCounter = AtomicInteger(0)
coroutineScope {
repeat(1000) {
launch(Dispatchers.Default) {
repeat(100) { atomicCounter.incrementAndGet() }
}
}
}
println("Atomic: ${atomicCounter.get()}") // exactly 100000
// Solution 3: Thread confinement
val singleThread = newSingleThreadContext("counter")
var confinedCounter = 0
coroutineScope {
repeat(1000) {
launch(Dispatchers.Default) {
withContext(singleThread) { repeat(100) { confinedCounter++ } }
}
}
}
println("Confined: $confinedCounter")
singleThread.close()
// Mutex for protecting shared resource
class BankAccount {
private var balance = 0.0
private val mutex = Mutex()
suspend fun deposit(amount: Double) = mutex.withLock {
delay(1); balance += amount
}
suspend fun getBalance() = mutex.withLock { balance }
}
val account = BankAccount()
coroutineScope {
repeat(100) { launch { account.deposit(10.0) } }
}
println("Balance: ${account.getBalance()}") // exactly 1000.0
}Use Cases
- Thread-safe shared state in coroutines
- Concurrent counter and accumulator patterns
- Protecting critical sections in async code
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
Coroutines — launch, async, and Structured Concurrency
Write concurrent code with Kotlin coroutines: launch, async/await, structured concurrency, and dispatchers.
Best for: Parallel API calls in backend services
Channels — Producer-Consumer with Coroutines
Communicate between coroutines with Channels: produce, actor pattern, fan-out/fan-in, and select.
Best for: Producer-consumer patterns in coroutines
Coroutine Mutex and Shared Mutable State
Safely manage shared state across coroutines: Mutex, atomic operations, and actor-based state.
Best for: Thread-safe counters and accumulators
Structured Concurrency Patterns
Master coroutine structured concurrency: coroutineScope, async/await, fan-out/fan-in, and parallel map.
Best for: Parallel I/O operations with concurrency limits