Home > Enterprise >  How does a Java virtual thread know when the thread is waiting?
How does a Java virtual thread know when the thread is waiting?

Time:11-27

When a virtual thread is blocked due to synchronized call, it's yielding, so the scheduler will unmount it from related Carrier thread.

I was wondering, how does a virtual thread know that it's currently at wait state and it's time to yield?

CodePudding user response:

It appears that you have a slight misconception: When a virtual thread is blocked due to synchronization, it is in fact yielding, but the scheduler will not unmount it from the related carrier thread. Instead, the carrier thread will be blocked, yielding. This is one of the current shortcomings of Project Loom, and it is well documented. The team says they might fix it in the future.

Specifically, in Coming to Java 19: Virtual threads and platform threads by Nicolai Parlog 2022-05 we read:

Unfortunately, there’s one more imperfection in the initial virtual thread proposal: When a virtual thread executes a native method or a foreign function or it executes code inside a synchronized block or method, the virtual thread will be pinned to its carrier thread. A pinned thread will not unmount in situations where it otherwise would.

(Emphasis mine.)

So for now, if you want to avoid blocking the carrier thread, you must refrain from using the synchronized keyword; instead, you must use a ReentrantLock or some other runtime library class that provides synchronization, such as CountdownLatch etc.

These classes have been modified in Java 19 and they now co-operate with the virtual thread mechanism precisely so as to allow virtual threads to be unmounted from carrier threads.

CodePudding user response:

At appropriate places in the code, the blocking is detected. For example

  public static void parkNanos(Object blocker, long nanos) {
        if (nanos > 0) {
            Thread t = Thread.currentThread();
            setBlocker(t, blocker);
            try {
                if (t.isVirtual()) {
                    VirtualThreads.park(nanos);<====
                } else {
                    U.park(false, nanos);
                }
            } finally {
                setBlocker(t, null);
            }
        }
    }
  • Related