Our use case for Virtual Threads was, as you suspected, I/O. (I say "was" because virtual threads — as we used them, anyway — were too unreliable. They would cause deadlocks that were punishing to debug, and cost us probably a full month of dev time, all included. We've since moved to using a custom `future` macro on top of a large threadpool.) We were doing an HTTP request fan-out with `http-kit` and then doing post-processing on the responses. We needed all of that to 1) not block the calling thread while 2) not exhausting the `clojure.core/future` threadpool. We figured that, while we could (and did) use a workaround, virtual threads could be a nice solution, so we reached to it.
Essentially here's the code for what we were doing:
```clojure
;; In a library function
(defn request-and-post-process [request]
(let [response (http-kit/request request)]
;; We use a `delay` to keep it a derefable output while avoiding using a thread
(delay (post-process @response))))
;; In a business logic function
;; Will be `deref`ed upstream
(defn async-concurrently-make-requests [requests]
(vthread
(->> requests
;; Concurrently kick off all requests
(mapv #(vthread @(request-and-post-process %)))
;; Aggregate
(mapv deref))))
```
Notice that `clojure.core/delay` is used. Turns out that `clojure.lang.Delay` uses `synchronized` in its `deref` method (see Clojure Q&A thread), which pins the virtual threads. `deref`ing the `delay` makes the calling virtual thread wait for as long as the HTTP request and post-processing takes to run, which can take 30 seconds in some cases. We were seeing not only pinning behavior here, but deadlock, which was unexpected. (The pinning is an issue for `clojure.lang.Delay`; the deadlock is an issue for the underlying JVM implementation of virtual threads, as far as I can tell. I believe there's an open ticket for it on bugs.openjdk.org.) To avoid the pinning, we used our custom `ReentrantLock`-based `delay`. However, there was other pinning going on in e.g. a JSON deserialization library that seems to have landed us in the deadlock zone despite the `delay` enhancement.
Let me know if all this answers your question! Happy to elaborate further.