Mutex is fair (fifo)
The mutex created is fair: lock is granted in first come, first served order. - kotlin doc
GT-Sandbox-Snapshot
Code
package com.glassthought.sandbox
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlin.time.Duration.Companion.seconds
// Demonstrate that Mutex in kotlin is fair - FIFO ordering of lock acquisition.
fun main() = runBlocking {
val mutex = Mutex()
val list = mutableListOf<Int>()
val howManyTasks = Runtime.getRuntime().availableProcessors()
val whenWeAreReadyToStartMillis = System.currentTimeMillis() + 1000
(1..howManyTasks).forEach {
launch(Dispatchers.Default) {
while (System.currentTimeMillis() < (whenWeAreReadyToStartMillis + it)) {
// spin wait, without delay so that the tasks get to the lock in the order of
// their "it" value
}
mutex.withLock {
// Delay: to make sure we will get the tasks to queue up on the lock
delay(howManyTasks.toLong() + 1)
list.add(it)
}
}
}
delay(3.seconds)
println("Actual : " + list)
println("Expected : " + (1..howManyTasks).toList())
}
Command to reproduce:
gt.sandbox.checkout.commit eb2c4982ff34283a9738 \
&& cd "${GT_SANDBOX_REPO}" \
&& cmd.run.announce "./gradlew run --quiet"
Recorded output of command:
Picked up JAVA_TOOL_OPTIONS: -Dkotlinx.coroutines.debug
Picked up JAVA_TOOL_OPTIONS: -Dkotlinx.coroutines.debug
Actual : [1, 3, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
Expected : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
Backlinks