Middle+
How does a mutex work in coroutines?
sobes.tech AI
Answer from AI
A Mutex in coroutines provides a mutual exclusion mechanism to protect shared resources from concurrent access by multiple coroutines.
Working principle:
- Lock acquisition: A coroutine that wants to access a protected resource calls the
lock()method. - Locking: If the mutex is free, the coroutine non-blockingly acquires it and continues execution. If the mutex is occupied by another coroutine, the calling coroutine suspends until the mutex is released.
- Releasing the mutex: After finishing with the protected resource, the coroutine calls the
unlock()method to release the mutex.
Key features in coroutines:
- Non-blocking
lock()(when acquiring a free mutex): Unlike traditional threads wherelock()can block the entire thread, in coroutines, if the mutex is free, acquisition occurs non-blockingly. - Coroutine suspension (when the mutex is occupied): If the mutex is busy, the calling coroutine does not block the thread but suspends until it is released. This frees the thread for executing other coroutines.
- Extension function
withLock: A convenient way to use a mutex that automatically acquires and releases it, even if an exception occurs inside the block.
Usage example:
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
val mutex = Mutex()
var counter = 0
suspend fun incrementCounter() {
mutex.withLock {
// Critical section - protected resource
counter++
delay(10) // Simulate work
println("Counter: $counter")
} // Mutex is automatically released here
}
fun main() = runBlocking {
repeat(100) {
launch {
incrementCounter()
}
}
delay(1000)
}
In this example, incrementCounter is a critical section that modifies the shared resource counter. The mutex ensures that only one coroutine accesses this section at a time, preventing race conditions. Using withLock simplifies mutex management.