What is thread pinning in virtual threads, and how do you diagnose and fix it?
Thread pinning happens when a virtual thread becomes stuck to its underlying carrier OS thread and cannot be unmounted from it during a blocking operation, which means the carrier thread itself is blocked and unavailable to run any other virtual thread instead of being returned to the pool. The two main causes are performing a blocking I/O operation inside a synchronized block, since the JVM cannot safely unmount a virtual thread while it holds a monitor, and calling into native code through JNI. You can diagnose pinning by running the JVM with the flag -Djdk.tracePinnedThreads=full, which prints a stack trace every time pinning actually occurs. The fix is to replace synchronized with ReentrantLock along any code path that also performs blocking I/O, since ReentrantLock, unlike the synchronized keyword, does support unmounting a virtual thread while it's held. For database access specifically, using a modern connection pool like HikariCP means virtual threads block while waiting for a connection from the pool rather than inside a synchronized block deep in the JDBC driver, avoiding pinning there as well.
Ready to master this question?
Generate a complete walkthrough — background, the full answer in plain language, a working code example explained line by line, a real-world scenario, common mistakes, and how this same question gets asked in different ways.
Sign in to generate a response