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

Busy loop in other thread delays EDT processing; possible livelock

    Details

    • Subcomponent:
    • Introduced In Version:
      8
    • CPU:
      x86_64
    • OS:
      generic

      Description

      FULL PRODUCT VERSION :
      java version "1.8.0_72"
      Java(TM) SE Runtime Environment (build 1.8.0_72-b15)
      Java HotSpot(TM) Server VM (build 25.72-b15, mixed mode)


      FULL OS VERSION :
      Linux dragon 4.1.12 #5 SMP PREEMPT Tue Dec 29 18:45:31 GMT 2015 x86_64 GNU/Linux
      Also seen on Windows, Mac OS X, and Raspberry Pi

      A DESCRIPTION OF THE PROBLEM :
      A thread executing a busy loop seems to delay execution of the AWT Event Dispatch Thread, despite that there should be no contention between the two threads and the system has unloaded processor cores available. Further, the test case I have provided exhibits 200% processor usage, suggesting that the EDT is in some kind of livelock. Attempts to debug the issue have been futile as JDWP-based debuggers fail to halt the busy thread (tried in Eclipse and Netbeans).

      See discussion on Stackoverflow:
      http://stackoverflow.com/questions/35154352/busy-loop-in-other-thread-delays-edt-processing/35157351

      Test program provided creates a busy loop (which runs for several seconds) when a Swing button is pressed, then displays a JOptionPane dialog after what should be a short delay (500ms sleep). In practice it is seen that either the dialog does not appear (or appears but contents do not render) until after the busy loop has finished (i.e. when it outputs a value to the terminal), or that the dialog does appear but does not respond to input until after the busy loop has finished. Thus it appears that the EDT processing is suspended by execution of the second thread, despite their being no contention between them and despite spare processing cores being available for execution. During this time, the 'top' program on linux shows 200% processor utilisation, which to me suggests livelock (or at least unexpected starvation) in the EDT.

      Problem is suppressed by using -Xint. On some but not all systems problem can be suppressed using -client.


      THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No

      THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Execute sample program provided with this report
      2. Click "Try me" button
      3. Click any button (yes/no/cancel) to close the resulting dialog


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      Expected:
      Between steps 2 and 3, there should be an approx 500ms delay before a dialog is displayed.
      After step 3, the dialog should close immediately.

      Actual:
      Between steps 2 and 3, there may be a long delay before the dialog appears visible, or it may appear on time but not rendered until some time later.
      After step 3, the dialog may not close until after a long delay.

      REPRODUCIBILITY :
      This bug can be reproduced often.

      ---------- BEGIN SOURCE ----------
      import java.awt.EventQueue;

      import javax.swing.JButton;
      import javax.swing.JFrame;
      import javax.swing.JOptionPane;

      public class MFrame extends JFrame
      {
          public static void main(String[] args)
          {
              EventQueue.invokeLater(() -> {
                  new MFrame();
              });
          }

          public MFrame()
          {
              JButton tryme = new JButton("Try me!");

              tryme.addActionListener((e) -> {
                  Thread t = new Thread(() -> {
                      int a = 4;
                      for (int i = 0; i < 100000; i++) {
                          for (int j = 0; j < 100000; j++) {
                              a *= (i + j);
                              a += 7;
                          }
                      }
                      System.out.println("a = " + a);
                  });

                  t.start();

                  // Sleep to give the other thread a chance to get going.
                  // (Included because it provokes the problem more reliably,
                  // but not necessary; issue still occurs without sleep call).
                  try {
                      Thread.sleep(500);
                  }
                  catch (InterruptedException ie) {
                      ie.printStackTrace();
                  }

                  // Now display a dialog
                  JOptionPane.showConfirmDialog(null, "You should see this immediately");
              });

              getContentPane().add(tryme);

              pack();
              setVisible(true);
          }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      Using Thread.yield() within the busy loop will suppress the problem.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                vlivanov Vladimir Ivanov
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                5 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: