How to prevent unintentional multithreading

The obvious way to move work off the current thread is withContext(Dispatchers.Default) {work()}

If I call this from and event loop context, however, then this has the dangerous side effect of executing the work() function in a multithreaded context, and coroutines launched deep within that function can now execute simultaneously in parallel threads. Its entire call graph is now required to be thread-safe.

Since concurrency is hard, I’d rather not impose that thread-safety requirement, and I don’t trust code to be thread-safe unless that is explicitly promised.

Is there an idiomatic way to dispatch work() off the current thread without multithreading all its internal coroutines?

I tried to find the answer before on Stackoverflow. And unfortunately looks like it is better to use Mutex for now …

Just create single-thread dispatcher and wrap all thread-sensitive work in withContext(MySingleThreadDispatcher). Everything will be done automatically by the library.

1 Like

This solution requires thread switch, which is better to avoid.

The thread switch occurs only once when you enter sensitive part. Also you should remember that thread switch is not quite expensive in coroutines. If you need only synchronization, not single thread executor, then Mutex is what you need.

1 Like

Thanks for the suggestion. My environment is a multi-threaded server, so having to maintain a bunch of single thread dispatchers would be pretty gross. If there’s no idiomatic way, then I guess I’ll write a dispatcher adapter so I can say, e.g., withSerialContext(Dispatchers.Default) { work() }

I answered your SO question: https://stackoverflow.com/a/59168180/5483526