Double Locking in Singleton Pattern in Java | Java @ Desk
Home » » Double Locking in Singleton Pattern in Java

Double Locking in Singleton Pattern in Java



Double Locking in Singleton Pattern in Java

In one of earlier posts, we learned Singleton design pattern in java & Singleton Design Pattern Without Cloning Java.


There is one more issue in this block of code that will come up in a multithreaded environment. In the below code, Thread.sleep is explicitly used in order to test the violation in multithreaded environment


public static SingletonDoubleLocking getSingletonDoubleLocking() {
  if (singletonDoubleLocking == null) {
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   singletonDoubleLocking = new SingletonDoubleLocking();
  }
  System.out.println("SingletonDoubleLocking - "
    + singletonDoubleLocking);
  return singletonDoubleLocking;
 }


Consider above code, where a method will be called in a multithreaded environment and so multiple threads enter the block and creates multiple instances which will violate the principal of Singleton Design Pattern as shown below :
package com.doubleLock;

public class ClientSingletonDoubleLocking implements Runnable {

 public static void main(String args[]) {
  ClientSingletonDoubleLocking clientSingletonDoubleLocking = new ClientSingletonDoubleLocking();
  int length = 5;
  Thread[] thread = new Thread[length];
  
  for (int index = 0; index < length; index++) {
   thread[index] = new Thread(clientSingletonDoubleLocking);
  }
  
  for (int index = 0; index < length; index++) {
   thread[index].start();
  }
 }

 @Override
 public void run() {
  SingletonDoubleLocking singletonDoubleLocking = SingletonDoubleLocking
    .getSingletonDoubleLocking();
 }
}


To avoid so, we need to perform a double locking to ensure no 2 objects are created in multithreading environment as shown below:
public static synchronized SingletonDoubleLocking getSingletonDoubleLocking() {
  if (singletonDoubleLocking == null) {
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   singletonDoubleLocking = new SingletonDoubleLocking();
  }
  System.out.println("SingletonDoubleLocking - "
    + singletonDoubleLocking);
  return singletonDoubleLocking;
 }

In the above implementation we are synchronizing the static method which is a lock on an Class object. This will ensure only one thread will enter the synchronize method





5 comments:

  1. I'm at a loss to understand how this is a double locked singleton. What's demonstrated above is a singleton no doubt but in order for it to be double locked it would required two null checks on the private singleton instance, one outside a synchronised block to avoid unnecessary locking (once the object has been instantiated) and one inside a synchronised block to avoid the potential race condition, in that order.

    This seems to be a perfectly valid vanilla singleton only and that needn't be a bad thing as described in this post http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

    ReplyDelete
  2. Could you please use my threading implementation and create a single object using the implementation you are saying.
    Let's test what you are saying.
    I tried the one you are saying but using multiple threads, I failed to achieve single object. So came up with this way. You can also try and let us know about it.

    ReplyDelete
  3. Why do you call it double-locking? I can see only one locking here: it's static synchronized method. Or did you mean double-checked locking? But it's not double-checked locking either.

    ReplyDelete
    Replies
    1. The double checked locking is achieved using 2 synchronized blocks inside a static method getSingletonDoubleLocking().
      The same has been achieved using the single synchronized at the method level. My intent behind writing double locking is that, the same can be achieved by making a method synchronized instead of double synchronized blocks inside a method

      Delete
    2. No, the point of double-checked locking is to use only one synchronized block and to avoid synchronization at all after the singleton is initialized. In double-checked locking, the condition instance == null has to be checked twice both outside and inside the synchronize block, that's why it's double-checked.

      Your solution is the classic one: getInstance() method has to be synchronized in the presence of multiple threads. And the word "double" just adds confusion in this case.

      Delete