Nov. 13, 2006, 4:07 p.m.

Double-Checked Locking Yet Again

Since I'm pretty much the only reader of this site, I can say with authority that my readers are getting annoyed by all this talk of singletons and double-checked locking. But alas, there's more. For a quick catch-up, see my recent post on lock-free singletons.

Today, someone pointed out to me that J2SE 5.0's volatile keyword makes a variant of double-checked locking safe. I found a reference to this on the double checked locking is unsafe page at UMD that points out the following:

The consensus proposal extends the semantics for volatile so that the system will not allow a write of a volatile to be reordered with respect to any previous read or write, and a read of a volatile cannot be reordered with respect to any following read or write.

So I extended my test code to include the new mechanism to find out what the performance difference was like. You can download the new test code to see if your results are different. The basic recipe looks like this:

  private volatile static Whatever2 inst=null;

  public static Whatever2 getInstance() { 
    if(inst == null) {
      synchronized(Whatever2.class) {
        if(inst == null) { 
          inst=new Whatever2();
        }       
      }     
    }   
    return inst;
  } 

The performance difference is dramatic. Same test as before, but now with the new volatile mechanism:

10000000 total requests, 4 threads for MT test
+......+......+......+......+......
Results:
 Atomics.mt
        [5130, 5033, 5136, 4803, 5122]
 Atomics.st
        [2657, 2709, 2712, 2715, 2715]
 Synchronized.mt
        [1735, 4720, 4779, 4865, 4735]
 Synchronized.st
        [508, 2684, 2677, 2680, 2685]
 Volatile.mt
        [92, 95, 92, 95, 101]
 Volatile.st
        [168, 164, 166, 164, 165]

This is consistently 20-40x faster and still less complicated than the atomics variety. If the memory model is correct, it might be worth the additional complexity. I still wouldn't recommend going back and reimplementing everything you've ever written just based on these. This was 10,000,000 iterations. If you're doing 10,000,000 of anything in five seconds, there are probably more important things to think about than how you access your singletons.

blog comments powered by Disqus