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