In our last post we have seen how to apply double locking for singleton object creation so that multiple threads do not enter the method and instantiate the object. Refer Double Checked Locking in Singleton.
We also must prevent object creation using the cloning of objects. So we must ensure that the singleton class must override the Object clone() method and throw the Exception in that.
Complete example of Singleton with Double Locking and without cloning as shown below. Thread.sleep is just for the demo purpose. Just to understand the flow as our memory does not work as fast as JVM :)
package com.doubleLock; public class SingletonDoubleLocking { private static SingletonDoubleLocking singletonDoubleLocking = null; private SingletonDoubleLocking() { } /** * synchronized so that multiple thread do not enter the method * @return SingletonDoubleLocking */ public static synchronized SingletonDoubleLocking getSingletonDoubleLocking() { if (singletonDoubleLocking == null) { System.out.println("Object is 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; } /** * Override clone method so that clone is avoided */ @Override public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException("Thrown this exception in order to avoid the creation of copy of this object"); } }
Client file to test the double locking and cloning
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(); } }
Output
Object is null
SingletonDoubleLocking - com.doubleLock.SingletonDoubleLocking@18a992f
SingletonDoubleLocking - com.doubleLock.SingletonDoubleLocking@18a992f
SingletonDoubleLocking - com.doubleLock.SingletonDoubleLocking@18a992f
SingletonDoubleLocking - com.doubleLock.SingletonDoubleLocking@18a992f
SingletonDoubleLocking - com.doubleLock.SingletonDoubleLocking@18a992f
As shown above inside a null check it enters only once even though the 5 threads have been started.
In order to check how cloning works put this blok of code in the client file run method and run the file again.
try { SingletonDoubleLocking singletonDoubleLocking2 = (SingletonDoubleLocking) singletonDoubleLocking.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); }
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.
ReplyDeleteThis 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
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.
ReplyDeleteThis 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
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.
ReplyDeleteThis 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