Synchronizing suspend functions


#1

Is there something like a Mutex for suspend functions that works in JS and in JVM? I need to prevent that a suspend function is executed concurrently by multiple callers. I tried synchronized but that does not work.

Here is some JVM code to illustrate my problem. It is not even working in JVM (IllegalMonitorStateException) but I think it makes it clear what I want to do:

class Test {
    var value: Int = 0

    suspend fun asyncFunc() = synchronized(this) {
        value++
        val result = value
        delay(100)
        assertTrue { value == result } // fails if asyncFunc is executed concurrently
    }

    @Test
    fun testMethod() = runBlocking {
        val job0 = async {
            asyncFunc() // mutates value
        }
        delay(10)
        async {
            asyncFunc() // mutates value concurrently (what I want to prevent)
        }.await()
        job0.await()
    }
}

What missing is IMHO something like:

suspend fun <R> synchronizedSuspend(lock: Any, block: () -> R): R

#2

Jup, I think what you are looking for is this:
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/index.html


#3

I’m aware of Mutex but Mutex is only available for JVM. Same is true for Channel which could have been helpful…

As far as I can see synchronized does nothing in JS. Why does it actually exist in JS? it doesn’t make sense in JS, does it? Find it a bit confusing, IMHO it should be removed from JS .

Are there plans to make the coroutine Mutex available for JS? I could implement something like Channel/Mutex in JS but want to check first if there isn’t something like this already.


#4

Mutex will be eventually ported to JS, too.