Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8339459

A virtualThread is blocked forever in synchronized block

XMLWordPrintable

    • x86_64
    • windows_10

      ADDITIONAL SYSTEM INFORMATION :
      Windows 10 x64 / Java 21.0.4

      A DESCRIPTION OF THE PROBLEM :
      A virtualThread can't enter a monitor forever when no virtual thread owns the monitor in synchronized block except setting the system property -Djdk.virtualThreadScheduler.maxPoolSize=1. And it's ok in the platformThread case.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the test
      >%java21_home%\bin\java VtBlockedForeverInSyncBlockTest
      [pt-lock-2#22] Worker#2 starts.
      [pt-lock-0#20] Worker#0 starts.
      [pt-lock-1#21] Worker#1 starts.
      [pt-lock-3#23] Worker#3 starts.
      [pt-lock-4#24] Worker#4 starts.
      [pt-lock-6#26] Worker#6 starts.
      [pt-lock-7#27] Worker#7 starts.
      [pt-lock-5#25] Worker#5 starts.
      [pt-lock-8#28] Worker#8 starts.
      [pt-lock-9#29] Worker#9 starts.
      [pt-lock-2#22] Worker#2 sleeping in lock ..
      [pt-lock-2#22] Worker#2 ends.
      [pt-lock-0#20] Worker#0 sleeping in lock ..
      [pt-lock-0#20] Worker#0 ends.
      [pt-lock-1#21] Worker#1 sleeping in lock ..
      [pt-lock-1#21] Worker#1 ends.
      [pt-lock-3#23] Worker#3 sleeping in lock ..
      [pt-lock-3#23] Worker#3 ends.
      [pt-lock-4#24] Worker#4 sleeping in lock ..
      [pt-lock-6#26] Worker#6 sleeping in lock ..
      [pt-lock-4#24] Worker#4 ends.
      [pt-lock-6#26] Worker#6 ends.
      [pt-lock-7#27] Worker#7 sleeping in lock ..
      [pt-lock-5#25] Worker#5 sleeping in lock ..
      [pt-lock-7#27] Worker#7 ends.
      [pt-lock-8#28] Worker#8 sleeping in lock ..
      [pt-lock-5#25] Worker#5 ends.
      [pt-lock-8#28] Worker#8 ends.
      [pt-lock-9#29] Worker#9 sleeping in lock ..
      [pt-lock-9#29] Worker#9 ends.
      [pt-sync-1#31] Worker#1 starts.
      [pt-sync-0#30] Worker#0 starts.
      [pt-sync-3#33] Worker#3 starts.
      [pt-sync-5#35] Worker#5 starts.
      [pt-sync-2#32] Worker#2 starts.
      [pt-sync-6#36] Worker#6 starts.
      [pt-sync-7#37] Worker#7 starts.
      [pt-sync-4#34] Worker#4 starts.
      [pt-sync-1#31] Worker#1 sleeping in sync ..
      [pt-sync-8#38] Worker#8 starts.
      [pt-sync-9#39] Worker#9 starts.
      [pt-sync-1#31] Worker#1 ends.
      [pt-sync-9#39] Worker#9 sleeping in sync ..
      [pt-sync-8#38] Worker#8 sleeping in sync ..
      [pt-sync-9#39] Worker#9 ends.
      [pt-sync-8#38] Worker#8 ends.
      [pt-sync-4#34] Worker#4 sleeping in sync ..
      [pt-sync-4#34] Worker#4 ends.
      [pt-sync-7#37] Worker#7 sleeping in sync ..
      [pt-sync-6#36] Worker#6 sleeping in sync ..
      [pt-sync-7#37] Worker#7 ends.
      [pt-sync-2#32] Worker#2 sleeping in sync ..
      [pt-sync-6#36] Worker#6 ends.
      [pt-sync-2#32] Worker#2 ends.
      [pt-sync-5#35] Worker#5 sleeping in sync ..
      [pt-sync-3#33] Worker#3 sleeping in sync ..
      [pt-sync-5#35] Worker#5 ends.
      [pt-sync-3#33] Worker#3 ends.
      [pt-sync-0#30] Worker#0 sleeping in sync ..
      [pt-sync-0#30] Worker#0 ends.
      [main] Platform thread tests pass!
      [vt-lock-0#40] Worker#0 starts.
      [vt-lock-0#40] Worker#0 sleeping in lock ..
      [vt-lock-1#42] Worker#1 starts.
      [vt-lock-3#44] Worker#3 starts.
      [vt-lock-4#45] Worker#4 starts.
      [vt-lock-5#46] Worker#5 starts.
      [vt-lock-6#47] Worker#6 starts.
      [vt-lock-7#48] Worker#7 starts.
      [vt-lock-8#49] Worker#8 starts.
      [vt-lock-9#50] Worker#9 starts.
      [vt-lock-2#43] Worker#2 starts.
      [vt-lock-0#40] Worker#0 ends.
      [vt-lock-1#42] Worker#1 sleeping in lock ..
      [vt-lock-1#42] Worker#1 ends.
      [vt-lock-3#44] Worker#3 sleeping in lock ..
      [vt-lock-4#45] Worker#4 sleeping in lock ..
      [vt-lock-3#44] Worker#3 ends.
      [vt-lock-4#45] Worker#4 ends.
      [vt-lock-5#46] Worker#5 sleeping in lock ..
      [vt-lock-5#46] Worker#5 ends.
      [vt-lock-6#47] Worker#6 sleeping in lock ..
      [vt-lock-6#47] Worker#6 ends.
      [vt-lock-7#48] Worker#7 sleeping in lock ..
      [vt-lock-7#48] Worker#7 ends.
      [vt-lock-8#49] Worker#8 sleeping in lock ..
      [vt-lock-8#49] Worker#8 ends.
      [vt-lock-9#50] Worker#9 sleeping in lock ..
      [vt-lock-9#50] Worker#9 ends.
      [vt-lock-2#43] Worker#2 sleeping in lock ..
      [vt-lock-2#43] Worker#2 ends.
      [vt-sync-0#55] Worker#0 starts.
      [vt-sync-0#55] Worker#0 sleeping in sync ..
      [vt-sync-2#57] Worker#2 starts.
      [vt-sync-1#56] Worker#1 starts.
      [vt-sync-3#58] Worker#3 starts.
      [vt-sync-3#58] Worker#3 sleeping in sync ..
      [vt-sync-4#59] Worker#4 starts.
      [vt-sync-1#56] Worker#1 sleeping in sync ..
      [vt-sync-5#60] Worker#5 starts.
      [vt-sync-1#56] Worker#1 ends.
      [vt-sync-6#61] Worker#6 starts. // Here the process hangs forever!


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The java process exits normally.
      ACTUAL -
      The java process hangs abnormally.

      ---------- BEGIN SOURCE ----------
      import java.util.concurrent.*;
      import java.util.concurrent.locks.*;

      class VtBlockedForeverInSyncBlockTest {
          
          static final int CONC = Integer.getInteger("conc", 10);
          static final long SLEEP = Long.getLong("sleep", 10);
          
          public static void main(String[] args) throws InterruptedException {
              var main = Thread.currentThread().getName();
              test(true);
              System.out.printf("[%s] Platform thread tests pass!%n", main);
              
              test(false);
              System.out.printf("[%s] Virtual thread tests pass!%n", main);
              
              System.out.printf("[%s] Test ok!%n", main);
          }
          
          static void test(boolean pt) throws InterruptedException {
              testLock(pt, CONC);
              testSync(pt, CONC);
          }
          
          static void testSync(boolean pt, int n) throws InterruptedException {
              ExecutorService executor = newExecutor(pt, true);
              try {
                  final Object lock = new Object();
                  for (var i = 0; i < n; ++i) {
                      var id = i;
                      executor.submit(()-> {
                          var thr = Thread.currentThread().getName();
                          var tid = Thread.currentThread().threadId();
                          System.out.printf("[%s#%d] Worker#%s starts.%n", thr, tid, id);
                          synchronized(lock) { // VTs blocked forever?
                              try {
                                  System.out.printf("[%s#%d] Worker#%s sleeping in sync ..%n",
                                      thr, tid, id);
                                  if (SLEEP >= 0) Thread.sleep(SLEEP);
                              } catch (InterruptedException e) {
                                  // Ignore
                              }
                          }
                          System.out.printf("[%s#%d] Worker#%s ends.%n", thr, tid, id);
                      });
                  }
              } finally {
                  executor.shutdown();
              }
              executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
          }
          
          static void testLock(boolean pt, int n) throws InterruptedException {
              ExecutorService executor = newExecutor(pt, false);
              try {
                  Lock lock = new ReentrantLock();
                  for (var i = 0; i < n; ++i) {
                      var id = i;
                      executor.submit(()-> {
                          var thr = Thread.currentThread().getName();
                          var tid = Thread.currentThread().threadId();
                          System.out.printf("[%s#%d] Worker#%s starts.%n", thr, tid, id);
                          lock.lock();
                          try {
                              System.out.printf("[%s#%d] Worker#%s sleeping in lock ..%n",
                                  thr, tid, id);
                              if (SLEEP >= 0) Thread.sleep(SLEEP);
                          } catch (InterruptedException e) {
                              // Ignore
                          } finally {
                              lock.unlock();
                          }
                          System.out.printf("[%s#%d] Worker#%s ends.%n", thr, tid, id);
                      });
                  }
              } finally {
                  executor.shutdown();
              }
              executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
          }
          
          static ExecutorService newExecutor(boolean pt, boolean sc) {
              var b = sc? "sync-": "lock-";
              ThreadFactory tf = pt? Thread.ofPlatform().name("pt-"+ b, 0).factory():
                  Thread.ofVirtual().name("vt-"+ b, 0).factory();
              return Executors.newThreadPerTaskExecutor(tf);
          }
          
      }

      ---------- END SOURCE ----------

      FREQUENCY : always


            alanb Alan Bateman
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: