The `synchronized` by itself does not cause any problems for virtual threads.
Only when one calls a blocking operation from synchronized, the thread is not unmounted. E.g. `synchronized (...) {blockingQueue.take()}`. Note that this is not a sane coding practice. (Calling a potentially long operation from within synchronized. The blockingQueue.take() does not need to be wrapped into synchronized. It has synchronization inside and plays well with virtual threads. Only when wrapped into the synchronized, the current implementation can not unmount the virtual thread.).
The JDK team works to remove quirks like pinning in the future versions.
No, synchronized is a very primitive lock implementation compared to what's available in java.util.concurrent.Locks.
However, it's built directly into the JVM specification, so it's difficult to change while keeping compatibility, while j.u.c.Locks is just a library. In other words, they can't change synchronized schematic, so they created j.u.c.Locks as a replacement.
> it's difficult to change while keeping compatibility
Actually, it is trivial to change. Just embed a ReentrantLock into every object and rewrite all calls to "synchronized"/"Object.wait" to use that lock.
Unfortunately, this would result in a bit of performance regression (increasing per-object memory footprint). To solve that would require turning ReentrantLock into a magical intrinsic, fully integrated with lock bytes in the object header. Which is actually not that hard either — other runtimes like Golang or Android VM solve problems like this on daily basis. Oracle, however…
... was taking years to land Project Loom. So long that people started calling it vaporware. Project Valhalla is still regarded as such by many. It had to be shipped as soon as it was usable, even though a few rough edges remain that really ought to be deburred.
As you indicate, the complexity lies in not burning too many bridges with existing users and use cases. This is something that Android regularly does and which Go never really had to do due to its shorter history and up-front design.
Since Java 1.5 in 2004. Twenty years this year. Before that it existed as a separate library developed by Doug Lee. I remember using that library before Java 1.5 was released. There is quite a bit of Java code out there that predates that of course. Also, lots of people continued to not grasp the essentials of that library and stuck with the primitives they knew. So there's a lot of code there with synchronized blocks post Java 1.5 instead of the more robust concurrency primitives that came with the java.util.concurrent package.
> 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
Isn't 'synchronized' effectively sugar for taking a kind of lock? Why can't it be treated uniformly by the scheduler?