Coroutines, Java Virtual Threads and Scoped Values

Is there a plan for native Kotlin support of Java Scoped Values (JEP 429)? (Is there a discussion or issue tracker where I can learn more about it?)

On a similar note, are there any plans for Kotlin coroutines to cooperate with Virtual Threads? I saw some references to VT/Project Loom on this forum but I’m not sure which bits are still relevant.

It seems like CoroutineContexts could do something similar, since they provide scoped, immutable but overridable data to all children. Something like:

data class MyData(val data: Foo) : CoroutineContext.Element {
    public companion object Key : CoroutineContext.Key<MyData>
}

withContext(MyData(data = foo)) {
    // access the data from any child context
    val foo = currentCoroutine[MyData]?.data
}

Roman Elizarov from JetBrains has said before that they won’t be using virtual threads in coroutine dispatchers because their dispatchers are highly tuned to avoid context switching and virtual threads don’t have an API that would allow them to replicate that.

I’m happy with CoroutineContext in pure Kotlin, but what I’m more interested in how would these new Java features interop with Kotlin.

To expand on my original post:

One of the headaches our team is facing now is that we depend on a couple of Java libraries that use ThreadLocal to pass “global” data around (e.g. OTEL context, ORM transaction/connection) with varied level of coroutine support/implementation. We also have our own code that passes context(s) around, which needs to survive calls to Java and Java calling back Kotlin.

At some point we’ll need to deal with code that is a mix of coroutines, threads, virtual thread, thread local storage, scoped values and coroutine context with varied interop support. Possibly even with cases when two 3rds party libs are incompatible.

My theory is that Java libs that use Thread Local are more likely to add support for virtual threads/scoped values than support for Kotlin coroutines.

I was wondering if for our own project, in code that we control, we could find some common ground and virtual threads and scoped values could in theory be one option, even if it means ditching Kotlin coroutines in our code. The result would be that we’d only have to support 2 approaches instead of 3.

Even if there is no interop between virtual threads/scoped values and Kotlin, I’d like to be aware what are the gotchas (like a case we came across some time ago when using Java re-entrant mutex which doesn’t work in Kotlin coroutines since the mutex requires lock and unlock operation to happen in the same thread, which is not guaranteed when using coroutines. Easy workaround, but we were not aware of this.)

On a similar note, are there any plans for Kotlin coroutines to cooperate with Virtual Threads?

Kotlin coroutines can already be run on Loom’s virtual threads and in some scenarios it performs better, according to this article:

According to the article, it’s a one-liner

val Dispatchers.LOOM: CoroutineDispatcher
    get() = Executors.newVirtualThreadPerTaskExecutor().asCoroutineDispatcher()

And now you can use this instead of, let’s say, Dispatchers.IO.

This is hardly a “coroutines on virtual threads”. The whole point of coroutines was to execute large number of coroutines on a few threads, by using continuations and manipulating the bytecode. If we can start many threads now, then coroutines don’t do too much else than degrading the performance by adding an overhead of the suspending code.

For me “coroutines on virtual threads” means not using the suspending code anymore as this is kind of redundant with what VTs provide. So we have a regular coroutines API and then we can choose if it compiles to suspending code or regular code using VTs. But as it was said above, not everything can be done with VTs. Coroutines use cooperative scheduling, VTs are pre-emptive.

Everything which can be done using Kotlin coroutines can be done utilizing non-public API from the Project Loom. My example: GitHub - Anamorphosee/loomoroutines: Library for the native Java coroutines utilizing Project Loom

I don’t know too much about non-public APIs of Loom. What about the above, is it possible to prevent Virtual Threads from making context switches?

No. But you don’t need VTs for coroutines. The non-public class jdk.internal.vm.Continuation allows to save and restore the call stack of a thread. So full-featured coroutines can be implemented just using it.

1 Like