[jdom-interest] Code to reproduce threading bug

Jason Hunter jhunter at servlets.com
Wed Dec 17 15:21:59 PST 2008


Hi Eric,

Thanks for the bug report and especially the test case.

I'm checking in a fix.  Here's the diff:

150c143,146
<         Namespace preexisting = (Namespace) namespaces.get(lookup);
---
 >         Namespace preexisting;
 >         synchronized (namespaces) {
 >             preexisting = (Namespace) namespaces.get(lookup);
 >         }
192c188,190
<         namespaces.put(lookup, ns);
---
 >         synchronized (namespaces) {
 >             namespaces.put(lookup, ns);
 >         }

Instead of synchronizing the entire method I'm synchronizing just the  
get and put calls.  That keeps the critical sections as small as  
possible.  With this change your test case now runs to completion  
every time reliably.

I didn't synchronize the two initial hash puts that take place in the  
static initializer block.  I'm wondering if there's any potential  
scenario where the map could be accessed by another thread at that  
point.  If someone can think of a way, write in.

-jh-

On Dec 16, 2008, at 2:21 PM, Eric Burke wrote:

> This quick and dirty hack demonstrates the threading bug in  
> Namespace.java that I posted earlier today. If I run this several  
> times, it eventually hangs forever.
>
> By adding the synchronized keyword to the  
> Namespace.getNamespace(...) method, the program seems to always work.
>
>
>
> import org.jdom.Namespace;
>
> import java.util.concurrent.CountDownLatch;
> import java.util.concurrent.ExecutorService;
> import java.util.concurrent.Executors;
>
> public class JdomThreadBug {
>
>     public static void main(String[] args) throws  
> InterruptedException {
>         ExecutorService es = Executors.newCachedThreadPool();
>
>         int numThreads = 100;
>         CountDownLatch startLatch = new CountDownLatch(1);
>         for (int i = 0; i < numThreads; i++) {
>             es.submit(new Namespacer(i * 10, i * 10 + 10,  
> startLatch));
>         }
>
>         startLatch.countDown();
>         System.out.println("*** DONE ***");
>         es.shutdown();
>     }
>
>     private static class Namespacer implements Runnable {
>         private final int min;
>         private final int max;
>         private final CountDownLatch startLatch;
>
>         private Namespacer(int min, int max, CountDownLatch  
> startLatch) {
>             this.min = min;
>             this.max = max;
>             this.startLatch = startLatch;
>         }
>
>         public void run() {
>             try {
>                 startLatch.await();
>                 for (int i = min; i < max; i++) {
>                     String prefix = "p" + i;
>                     String uri = "u" + i;
>                     System.out.println("Getting namespace " + prefix  
> + ":" + uri);
>                     Namespace.getNamespace(prefix, uri);
>                     System.out.println("Got namespace " + prefix +  
> ":" + uri);
>                 }
>             } catch (InterruptedException e) {
>                 Thread.currentThread().interrupt();
>             }
>         }
>     }
> }
>
>
> -- 
> Eric M. Burke
> http://www.linkedin.com/in/ericburke
> 314-494-3185 (mobile)
> 636-272-3298 (home)
> _______________________________________________
> To control your jdom-interest membership:
> http://www.jdom.org/mailman/options/jdom-interest/ 
> youraddr at yourhost.com



More information about the jdom-interest mailing list