Virtual threads and structured concurrency question 114 of 180 senior
What is pinning, and what causes it?
- A thread being assigned to a specific CPU core
- Correct: A virtual thread that cannot unmount while blocked, so it occupies its carrier: caused by blocking inside
synchronized(before JDK 24) or inside a native frame - The scheduler refusing to steal work
- A GC pause
If a virtual thread blocks while it holds a monitor, the JVM cannot unmount it, because the monitor is tied to the carrier's stack frame. The carrier is occupied for the whole blocking call. With a default of one carrier per core, a handful of pinned threads can stop the entire application while the CPU sits idle.
Measured on Java 21, a synchronized block around a blocking call cost about 6x throughput against
the same code with a ReentrantLock. Native frames (JNI) pin as well and cannot be fixed by swapping a
lock.
Diagnosis: the jdk.VirtualThreadPinned JFR event, or -Djdk.tracePinnedThreads=full before JDK 24,
which removed that flag. The fix before
JDK 24 is to replace synchronized around blocking calls with ReentrantLock. JEP 491 in JDK 24
removed most monitor pinning, so on newer JVMs this is largely historical, but the question is still
asked and the JFR event is still the way to check.
Quiz yourself on Virtual threads and structured concurrency Suggest a correction