views:

366

answers:

3

I was reading the article Double-checked locking and the Singleton pattern, on how double checked locking is broken, and some related questions here on stackoverflow.

I have used this pattern/idiom several times without any issues. Since I have been using Java 5, my first thought was that this has been rectified in Java 5 memory model. However the article says

This article refers to the Java Memory Model before it was revised for Java 5.0; statements about memory ordering may no longer be correct. However, the double-checked locking idiom is still broken under the new memory model.

I'm wondering if anyone has actually run into this problem in any application and under what conditions.

+2  A: 

It would be difficult for someone to be sure that their application had actually been hit by a double-checked lock failure. Indeed, many applications that used this idiom may never experience the problem for a variety of reasons.

However, that doesn't mean that you should use it. The mere fact there is a non-quantifiable probability of failure should be sufficient to persuade you not to use double-checked locking, especially since there are safe alternatives.

You've just been lucky.

Stephen C
+2  A: 

We had an application which used a broken double-check idiom, and it functioned perfectly for a very long time - no, in fact, I have never experienced problems with this idiom. Of course I fixed it regardless of that.

I guess one of the reason of this is that thread visibility will eventually attained in real world. And once attained, it stays. So yes it will be very difficult to detect whether the problem has happened.

I believe the hashCode() implementation of String partially relies on this fact.. Threads calculate hashCode while they don't see the cache, but eventually they start to see. Meanwhile, duplicate calculation means just some wasted cpu time, and the benefit of avoiding the memory effect of volatile semantics trumps this wasted effort (at least that's why they implemented it that way I guess). In other words, there ARE valid use of this "broken" double-check idiom.

Obviously, one has to think and measure a lot before using it.

EDIT:

there ARE valid use of this "broken" double-check idiom.

This was misleading.. Idiom that has valid use is (actual String.hashCode() implementation):

 /** Cache the hash code for the string */
 private int hash; // Default to 0 

 public int hashCode() {
       int h = hash;
       if (h == 0) {
           int off = offset;
           char val[] = value;
           int len = count;

          for (int i = 0; i < len; i++) {
               h = 31*h + val[off++];
           }
          hash = h;
      }
      return h;
  }
Enno Shioji
String hashCode is an example of a situation where it does not matter that 2 threads might do the same work. It shows that locking is not always needed. This is not a broken double check. A broken double check has the pattern `if (test) { synchronised { if (test) { //... } } }`
rsp
A: 

Illustrating example of Singleton with respect to Double-checked locking that looks Clever but broken The start of a synchronization block guarantees that you see the latest data but does not gaurantee reordering, you cannot expect a consistent view of data unless you are also in a synchronized block.it doesn't guarantee, that variables modifications done within synchronized section will be visible to other threads. Only the threads that enters the synchronized block is guarantieed to see the changes. This is the reason why double checked locking is broken - it is not synchronized on reader's side. Reading thread may see, that singleton is not null, but singleton data may not be fully initialized (visible).

On the othe hand Ordering is provided by volatile which guarantees ordering, for instance write to volatile singleton static field guaranties that writes to the singleton object will be finished before the write to volatilie static field. It doesn't prevent creation singleton of two objects, this is provided by synchronize Class final static fields doesn't need to be volatile, In Java JVM takes care of this problem.

More can be found here http://www.javaworld.com/jw-02-2001/jw-0209-double.html http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Sudhakar Kalmari