Wednesday 30 March 2016

Volatile and double-checked locking

https://en.wikipedia.org/wiki/Singleton_pattern#Java_5_solution

This is a lazy initialization of singleton.

What does volatile do here?

1:  public final class SingletonDemo {  
2:    private static volatile SingletonDemo instance;  
3:    private SingletonDemo() { }  
4:    public static SingletonDemo getInstance() {  
5:      if (instance == null ) {  
6:        synchronized (SingletonDemo.class) {  
7:          if (instance == null) {  
8:            instance = new SingletonDemo();  
9:          }  
10:        }  
11:      }  
12:      return instance;  
13:    }  
14:  }  
Well, volatile ensures one thread can always read the up-to-date value of the variable updated by another thread.

What happens if we remove volatile?

OK, brain exercise time. Suppose two threads A and B come to this getInstance() method.

At time 100: Both A and B arrive at line 5
At time 101: A enters the synchronized block, B waits outside
At time 105: A exits the synchronized block at line 12
At time 106: B enters the synchronized block at line 7

Question: For thread B, is 'instance' equal to null now? Not necessarily without the volatile keyword. It might still seem to be null to B although it has in fact been assigned some value.

Next question: is there any advantage of using double-checked lock over the following implementation, which looks much neater.
1:  public final class SingletonDemo {  
2:    private static SingletonDemo instance = null;  
3:    private SingletonDemo() { }  
4:    public static synchronized SingletonDemo getInstance() {  
5:      if (instance == null) {  
6:        instance = new SingletonDemo();  
7:      }  
8:      return instance;  
9:    }  
10:  }  

I guess when the number of threads is high, the 2nd implementation is slower because of the synchronized keyword on the method. For the 1st implementation, once the object has been created, the synchronized block won't be executed at all.