« Return to Thread: Code to reproduce threading bug

Re: Code to reproduce threading bug

by jhunter :: Rate this Message:

Reply to Author | View in Thread

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@...

_______________________________________________
To control your jdom-interest membership:
http://www.jdom.org/mailman/options/jdom-interest/youraddr@...

 « Return to Thread: Code to reproduce threading bug