Uploaded image for project: 'XMLBeans'
  1. XMLBeans
  2. XMLBEANS-345

Setting the same variable to multiple properties in multi-threaded environment causes deadlocking

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Critical
    • Resolution: Invalid
    • Version 2.3, Version 2.3.1
    • None
    • XmlObject
    • None
    • Microsoft Windows XP [Version 5.1.2600], single-core
      java version "1.5.0_10"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_10-b03)
      Java HotSpot(TM) Client VM (build 1.5.0_10-b03, mixed mode)

    Description

      When setting a property on many XmlBeans objects with a single large variable, all threads concerned will block with this stacktrace:

      java.lang.Object.wait:-2
      java.lang.Object.wait:-1
      org.apache.xmlbeans.impl.common.Mutex.acquire:33
      org.apache.xmlbeans.impl.common.GlobalLock.acquire:27
      org.apache.xmlbeans.impl.values.XmlObjectBase.set:1944

      The test below sets a Type on it's Document and illustrates the problem. I can't publish the actual schema and namespace, but to give an idea of size, the XML object is about 90 KB of complex data (multiple namespaces, hundreds of elements, embedded CDATA).

      A workaround has been included in commented-out form.

      import java.io.File;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      import java.util.Map;

      import org.apache.xmlbeans.XmlException;

      import tests.LargeDataStructureType;
      import tests.LargeDataStructureDocument;

      public class BlockingExample {

      public static void main(String[] args) throws InterruptedException, XmlException, IOException {

      LargeDataStructureDocument doc = LargeDataStructureDocument.Factory.parse(new File("exampleFile.xml"));

      LargeDataStructureType type = doc.getLargeDataStructureType();

      List<Setter> setters = new ArrayList<Setter>();

      for(int i = 0; i != 20; i++) setters.add(new Setter(key));

      for(Setter s : setters) s.start();

      Thread.sleep(10000);

      Map<Thread,StackTraceElement[]> map=Thread.getAllStackTraces();
      for(Thread t:map.keySet()){
      StackTraceElement[] ss=map.get(t);
      System.out.println("Thread:"t.getName()":"t.getState()":"+t.isAlive());

      if(ss!=null) {
      for(StackTraceElement s:ss)

      { System.out.println("\t"+s.getClassName()+"."+s.getMethodName()+":"+s.getLineNumber()); }

      }
      }

      System.exit(0);

      }
      }

      class Setter extends Thread {

      private static int counter = 0;

      private LargeDataStructureType type;

      Setter(LargeDataStructureType type)

      { /* * This reproduces the behaviour */ this.type = type; /* * This also reproduces the behaviour */ // this.type = (LargeDataStructureType)type.copy(); /* * This is a reliable workaround. */ // this.type = LargeDataStructureType.Factory.newInstance(); // type.set(type); }

      public void run() {
      while(true) {
      LargeDataStructureDocument obj = LargeDataStructureDocument.Factory.newInstance();
      obj.setLargeDataStructure(key);

      if(counter++ % 10000 == 0)

      { System.out.print("."); }

      }
      }

      }

      This produces the following output:

      .Thread:Thread-7:WAITING:true
      java.lang.Object.wait:-2
      java.lang.Object.wait:-1
      org.apache.xmlbeans.impl.common.Mutex.acquire:33
      org.apache.xmlbeans.impl.common.GlobalLock.acquire:27
      org.apache.xmlbeans.impl.values.XmlObjectBase.set:1944
      tests.LargeDataStructureTypeImpl.setLargeDataStructure:xx
      be.inglease.wel.Setter.run:64
      Thread:Thread-13:WAITING:true
      java.lang.Object.wait:-2
      java.lang.Object.wait:-1
      org.apache.xmlbeans.impl.common.Mutex.acquire:33
      org.apache.xmlbeans.impl.common.GlobalLock.acquire:27
      org.apache.xmlbeans.impl.values.XmlObjectBase.set:1944
      tests.LargeDataStructureTypeImpl.setLargeDataStructure:xx
      be.inglease.wel.Setter.run:64

      (...etc. for 20 threads)

      The expected output would just be lots of dots followed by various stacktraces.

      Attachments

        Activity

          People

            Unassigned Unassigned
            ian.sollars Ian Sollars
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: