JDK-4760477 : JTextArea.append(String) is not ThreadSafe
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.3.1,1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: solaris_2.6,windows_2000
  • CPU: x86,sparc
  • Submitted: 2002-10-09
  • Updated: 2003-02-25
  • Resolved: 2003-02-25
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Description

Name: sv35042			Date: 10/09/2002


FULL PRODUCT VERSION :
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)

FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
JTextArea.append() is not ThreadSafe (doc says it is)
sometimes depending on when the threads get their turn to run
deadlock occurs

AWT-EventQueue calls
RepaintManager.validateInvalidComponents()
Container.validate() --> getTreeLock() [A1]
:
BasicTextUI.getPreferredSize() --> readLock() [A2]

Another Thread calls
JTextArea.append()
:
AbstractDocument.insertString() --> writeLock() [B1]
:
BasicTextUI.setView()
Container.removeAll() --> getTreeLock() [B2]

whenever B1 is called in between A1 and A2 deadlock occurs as
A2 waits for B1 to finish
B1 waits for B2 to finish
B2 waits for A1 to finish
A1 waits for A2 to finish

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Difficult to reproduce in a different environment due to
mulpiple threads.
Running the code below with breakpoints at the different
points in the code above, then continuing different threads
at the points noted is a possible way of reproducing the
problem.
In my actual code (confidentual) by typing in exactly the
same thing I can make it occur most of the time.  Slight
deviations in what a type in, like shorter or longer make
the problem less likely to occur.

EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected: Never to go into deadlock.
Actual: deadlock

This bug can be reproduced often.

---------- BEGIN SOURCE ----------
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Test {
  public static void main(String args[]) {
    JFrame frame = new JFrame();
    final JTextArea text = new JTextArea();
    frame.getContentPane().add(new JScrollPane(text));
    for (int i = 0; i < 5; i++) {
      new Thread(new Runnable() {
        public void run() {
          while (true) {
            try {
              Thread.sleep((long)(500 * Math.random()));
            }
            catch (InterruptedException ex) {}
            text.append("word ");
            if (Math.random() < 0.05) {
              text.append("\n");
            }
          }
        }
      }).start();
    }
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
  }
}
---------- END SOURCE ----------

CUSTOMER WORKAROUND :
use SwingUtilities.invokeLater when calling JTextArea.append()
(ignore what the doc says)
(Review ID: 145815) 
======================================================================