javaproject-loom

Synchronize block pinning virtual thread


I am an enthusiast and am wondering about virtual threads. In the docs it says that one of the conditions to pin the thread is in a synchronized block, and in those cases to use a semaphore. Here are the docs to the JEP https://openjdk.org/jeps/444

There are two scenarios in which a virtual thread cannot be unmounted during blocking operations because it is pinned to its carrier: When it executes code inside a synchronized block or method, or When it executes a native method or a foreign function.

Is this due to the implementation of a synchronized block being a spin lock and the thread does not stop executing instructions, while a semaphore will yield after a few attempts?


Solution

  • The JEP 425 gives, in my opinion, more detailed technical information on the issue you raised. It mentions java.util.concurrent.locks.ReentrantLock. A synchronization primitive Semaphore also exists in Java Concurrency and it uses the same AbstractQueuedSynchronizer a.k.a. the AQS as ReentrantLock does, so it is conceptually the same, but semantic of ReentrantLock is very similar to that of synchronized block, which is advised to be replaced. But this is a technical remark.

    The key difference is that ReentrantLock, AQS, direct Unsafe/VarHandle and similar synchronization primitives use non-blocking CAS technique while synchronized blocks the thread, at least in a case of contention.

    To understand the difference between the two, I'd advise to learn more about CAS and/or experiment with Java Atomic* methods compareAndSet.

    As a side note, ReentrantLock, AQS and few other other synchronization primitives still may block the thread (in fact, it is necessary, generally speaking), it is done by calling LockSupport.park methods. Under the hood, LockSupport.park also invokes a native method, but for some reason this is not (or lesser?) problem for Virtual Threads.