Double Check locking

I attended a Java One Session TS-1630 (The Java Memory Model: The building block of concurrency) which discussed the memory model and the relationship with synchronization, volatile, and the concurrent libraries. Part of the session was of course about double check locking. The specification on the memory model as of JSE 5 has codified the volatile keyword to allow another correct solution for double check locking. I did a very rough performance check for three correct solutions for lazy initialization. The test obtained the lazily created instance 10,000,000 times and invoked a mutating method on the class. Solution 1: Initialize the value in a static block (this can be implicit)
private static ClassSingleton instance = 
new ClassSingleton();

public static ClassSingleton getDefault() {
return instance;
}
The VM guarantees this behavior and the code is straightforward, this method was the fastest (on my machine the test took roughly 1092 milliseconds). Solution 2: Use volatile to make the double check locking pattern work as intended.
    private static volatile VolatileSingleton instance;

public static VolatileSingleton getDefault() {
if (instance==null) {
synchronized(VolatileSingleton.class) {
if (instance == null) {
instance = new VolatileSingleton();
}
}
}
return instance;
}

The volatile keyword is used here to ensure appropriate memory consistency. This was the second fastest approach but not by much (1161 milliseconds, about 6% slower than 1). Solution 3: Use a synchronized method but not double check locking:


 private static SynchronizedSingleton instance;
    
    
public static synchronized SynchronizedSingleton getDefault() {
    if (instance == null) {
        instance = new SynchronizedSingleton();
    }

    return instance; }

 This is also straightforward, just adding a synchronized keyword to ensure that memory will be consistent when determining if the instance is null. This technique was also the slowest (1202 milliseconds, about 9% slower than 1 and 3% slower than 2).

Comments:

Have you seen this stuff? http://www-128.ibm.com/developerworks/java/library/j-jtp04186/ IMHO this is an invitation to disaster. Only wizards should be allowed to do this sort of coding.

Posted by Andrew Sherman on May 22, 2006 at 01:55 AM PDT #

hi andrew,

i guess chris got this advice from one of those Wizards.
BR,
~A

Posted by anjan bacchu on May 22, 2006 at 07:49 AM PDT #

The AtomicReference is another way, I can post the results of this test. As Andrew points out, there isn't much benefit from using one of the other subtle approaches.

Posted by guest on May 22, 2006 at 10:29 AM PDT #

Not only is there not much benefit, there is a danger. The code example you provided will compile under JDK 1.4 however it is not guaranteed to work there. The memory model did not become codified until 1.5. Given the number of evil threading bugs that the double check locking idiom has been responsible for (pre JDK 1.5), it is worth reiterating the JRE dependency. I am hoping your AtomicReference test proves to be faster than the double checked locking idiom. If it proves to be, there would appear to be no reason to ever use double check locking again. The AtomicReference approach has the benefit of only being able to compile and run in JDK 5 and above, where it will always work.

Posted by Michael Ottati on May 31, 2006 at 03:37 AM PDT #

Post a Comment:
Comments are closed for this entry.
About

cwebster

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today