does-work-in-JVM for coroutines

While @Synchronized is not supported outside of JVM, see 'synchronized' Is Not Supported. Experimentally (on MAC OS) It does in fact work within the JVM.

Here is an example:

GT-Sandbox-Snapshot: With @Synchronized the count is a expected; Without its not.

Code

package com.glassthought.sandbox

import gt.sandbox.util.output.Out
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

var sharedCounter = 0 // Shared resource

val out = Out.standard()

@Synchronized
fun incrementSharedCounter(){
  sharedCounter++
}

fun main() = runBlocking {
  val coroutineCount = 5
  val iterationsPerCoroutine = 1000000

  val timeTaken = measureTimeMillis {
    val jobs = List(coroutineCount) { idx ->
      launch(CoroutineName("coroutine-$idx") + Dispatchers.IO) {
        out.info("Starting coroutine $idx")

        repeat(iterationsPerCoroutine) {
          incrementSharedCounter()
        }
      }
    }

    jobs.forEach { it.join() } // Wait for all coroutines to finish
  }

  out.info("Expected counter value: ${coroutineCount * iterationsPerCoroutine}")
  out.info("Actual counter value: $sharedCounter")
  out.info("Time taken: $timeTaken ms")
}

Command to reproduce:

gt.sandbox.checkout.commit 69e54170ef0e40dc3a55 \
&& cd "${GT_SANDBOX_REPO}" \
&& cmd.run.announce "./gradlew run --quiet"

Recorded output of command:

[elapsed:   48ms][⓹/tname:DefaultDispatcher-worker-6/tid:25][coroutine:coroutine-3] Starting coroutine 3
[elapsed:   48ms][⓺/tname:DefaultDispatcher-worker-4/tid:23][coroutine:coroutine-4] Starting coroutine 4
[elapsed:   48ms][⓷/tname:DefaultDispatcher-worker-3/tid:22][coroutine:coroutine-1] Starting coroutine 1
[elapsed:   48ms][⓶/tname:DefaultDispatcher-worker-1/tid:20][coroutine:coroutine-0] Starting coroutine 0
[elapsed:   48ms][⓸/tname:DefaultDispatcher-worker-2/tid:21][coroutine:coroutine-2] Starting coroutine 2
[elapsed:  217ms][🥇/tname:main/tid:1][coroutine:unnamed] Expected counter value: 5000000
[elapsed:  217ms][🥇/tname:main/tid:1][coroutine:unnamed] Actual counter value: 5000000
[elapsed:  218ms][🥇/tname:main/tid:1][coroutine:unnamed] Time taken: 190 ms

This makes sense as if @Synchronized works by making sure only one thread can enter the block, then the co-routines must execute on some thread at some point. And that is where the @Synchronized takes effect./