Welcome! Please see the About page for a little more info on how this works.

0 votes
in Sequences by
closed by

I have a service written in Clojure 1.11 and service is running on Jetty 12.
I tried to run service on Java 21 using virtual threads in Jetty.
There are following constraints preventing virtual thread's unmounting:

A virtual thread cannot be unmounted during blocking operations when
it is pinned to its carrier. A virtual thread is pinned in the
following situations:
- The virtual thread runs code inside a synchronized block or method
- The virtual thread runs a native method or a foreign function (see Foreign Function and Memory API)

i ran service with '-Djdk.tracePinnedThreads=full' key and found that LazySeq
synchronized LazySeq methods pin the virtual thread:

clojure.lang.LazySeq.sval(LazySeq.java:42) <== monitors:1
clojure.lang.LazySeq.seq(LazySeq.java:51) <== monitors:1

(By the way, same problem is raised by synchornized Delay deref method)

As i see Clojure stdlib implementation and Clojure internal stuff itsself use 'synchronized' approach heavily which is incompatible with virtual thread constraints.
I understand that there is a huge amount of code and it is mega expensive to adapt it to be virtual thread's friendly but maybe there are some plans about being compatible with virtual threads constraints.


Hi Andray, synchronized use by itself is not inherently bad, it's only an issue when the synchronized is held over something that's blocking, so very interested to understand what you're doing in the lazy seq in this case - are you blocking on external I/O (reading from a stream/reader), or something else? If you could add more detail in the linked original thread, that would help us keep information in one place as we consider alternatives.
Thanks for your attention, Alex!
I guess my banal scenarioses will just bring noise to already clarified "Request to find and eliminate virtual thread pinning" issue:
- blocking IO call from function called from clojure.core/map
- blocking IO call from clojure.core/deref