kotlinkotlin-coroutines

Is mutating shared state race-free when using CoroutineDispatcher.limitParallelism(1)?


While trying to protect shared state in a singleton from race-conditions, I came across the limitParallelism API.

If I use limitParallelism(1), and only read or write the shared state within that coroutine scope, am I guaranteed that it is data-race free?

On one hand, limitParallelism(1) implies serial access of the state, so it sounds like that would be OK, but on the other hand, the docs does specifically mention that Note that there is no guarantee that the underlying system thread will always be the same, which makes me wonder if more protection like @Volatile or even Mutex would be needed.

Edit 1: I am running Kotlin on the JVM, in case determining this requires looking at the specific platform and/or platform-specific implementations.

Edit 2: To further illustrate what I am looking for, ExecutorService has a note on memory consistency that guarantees the happens-before relationship. Is there a similar note anywhere in the coroutines documentation?


Solution

  • I could not find any documentation in the relevant interfaces that provides such a guarantee, and since the coroutine dispatcher can have any implementation, I am inclined to say that this is not guaranteed in general (and therefore left up to the implementation of the dispatcher).

    Looking at the current implementation (with the understanding that it doesn't imply much about guarantees), LimitedDispatcher I don't see any synchronization on the dispatched runnable (Worker.run) that would give the sort of memory consistency guarantees that I was asking about.

    That said, on JVM, since Executor and ExecutorService provides such a guarantee, any dispatchers backed by these Java classes will have these guarantees.