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?
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 primitiveSemaphorealso exists in Java Concurrency and it uses the sameAbstractQueuedSynchronizera.k.a. the AQS asReentrantLockdoes, so it is conceptually the same, but semantic ofReentrantLockis very similar to that ofsynchronizedblock, which is advised to be replaced. But this is a technical remark.The key difference is that
ReentrantLock, AQS, directUnsafe/VarHandleand similar synchronization primitives use non-blocking CAS technique whilesynchronizedblocks 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*methodscompareAndSet.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 callingLockSupport.parkmethods. Under the hood,LockSupport.parkalso invokes a native method, but for some reason this is not (or lesser?) problem for Virtual Threads.