Virtual threads in Java can get pinned to their carrier platform thread in several scenarios, negating their scalability benefits. The main pinning causes are: synchronized methods/blocks, native method calls, static initializer blocks, and custom class loaders. The post demonstrates how to detect pinning using Java Flight Recorder (JFR) and the -Djdk.tracePinnedThreads VM flag. The fix for synchronized blocks is to replace them with ReentrantLock from java.util.concurrent.locks, which is Loom-aware and does not cause pinning. JDK 24+ (via JEP-491) resolves the synchronized keyword pinning at the JVM level, with JMH benchmarks showing dramatically improved throughput (e.g., ~8x at 1000 concurrency) in JDK 25 vs JDK 21. Native methods, class loaders, and static initializers still cause pinning in all versions.

8m read timeFrom feeds.feedblitz.com
Post cover image
Table of contents
1. Introduction2. Virtual Thread Pinning Scenarios3. Implement Synchronization Without Pinning4. Pinning Scenarios Resolved in JDK 245. Benchmark6. Conclusion

Sort: