JEP 491: Synchronize Virtual Threads without Pinning
Last updated
Last updated
In earlier Java versions, using synchronized
blocks could pin a virtual thread to a platform thread, blocking scalability.
🔐 JEP 491 (Java 24) removes that limitation:
Virtual threads now don't get pinned during
synchronized
blocks on object monitors.
RUN :
This is very basic example where thread sleep 100ms within synchrronized block. Although there is 100 virtual threads per core prorgam should finish within 100-200ms
When a virtual thread enters a synchronized
block, it may pin the carrier platform thread (i.e., the actual OS thread backing the virtual thread during execution).
Blocking calls like Thread.sleep()
inside a synchronized
block would prevent the JVM from unmounting the virtual thread, because JVM assumes the monitor might need to be released immediately (e.g., if another thread is waiting).
Therefore, the platform thread gets blocked during that sleep
, even if there’s no actual contention.
With 1000 virtual threads, and only one platform thread in the pool, the runtime would be:
The JVM was improved to detect that in non-contended synchronized blocks, pinning is unnecessary, and allows the virtual thread to yield the platform thread during blocking.
So now, each sleeping virtual thread unmounts cleanly, and the one platform thread is reused.
The result: it completes in just over 100 ms, not 100 seconds.