Imagine, what if we had a magic robot which can give us A Golden Egg or A Dragon Egg for us.
Oh yes, either we would be filthy rich or we would could have dragons protecting us, but not both.
Why not both simultaneously ?
Because then the robot says - "Master, once you tell me I need to give you a Golden Egg, I can only give you a Golden Egg and the SAME Golden Egg every time, exactly the same as the previous one, same in shape, size, color, exactly ONE-OF-A-KIND Golden Egg. You cannot make that Golden Egg yourself and everytime you need a Golden Egg you need to ask me. But if you need a Dragon Egg, you need to throw me away and get another me. Ask me for a Dragon Egg and then onwards you will get only ONE-OF-A-KIND and the SAME Dragon Egg. So, Master, kindly be careful with what you wish for !"
OR
Decoding what Mr. Robot says
So, what does the the Robot mean by what he says to his master ? Let's see.
The Robot says three crucial keywords that we should watch out for :
1. Only one type of Egg at a time
2. ONE-OF-A-KIND
3. Exactly same.
This means, once Mr. Robot is being told by his master that he needs a Golden Egg, the Robot's ONLY JOB IN LIFE is to produce the SAME GOLDEN EGG every time his master asks him. There's no chance the Robot is going to give a Dragon Egg ever, not until he is being re-programmed to produce a Dragon Egg.
The Master thinks, "Whoa, what a waste, I thought this guy would be much more useful than that."
He further ponders, "Do I really need a Robot, then ?"
But, wait, what this Robot-Master story has to do with us ? We would never get a Golden Egg or a Dragon egg even though we wish we got. That's just a dream.
But then one day Master walks up to Mr. Robot and asks him,
"Mr. Robot, what's your name ?"
Robot says - "My friends always thought I was a simpleton, but when they found out I can produce a Golden Egg and the same egg every time, they named me a Egg Singleton. I am programmed by the Singleton Design Pattern, master !"
Master - "Whoa, now, what's that ? Is that some kind of a sorcery ?"
Robot - "No, that's my design."
Mr. Robot on the Singleton Design Pattern
Robot says to the Master - "By Singleton Design Pattern I mean, I create only ONE-OF-A-KIND object and I let a global point of access to it."
"Once I am told to give a Golden Egg, I not only keep giving you the SAME Golden egg every time,
but the SAME Golden Egg to everyone else across the world. I am loyal to you Master." - Robot
but the SAME Golden Egg to everyone else across the world. I am loyal to you Master." - Robot
The Master thinks he has not understood anything and then he goes to the guy who programmed the Robot
and tells him that the Robot is strange with his words. He says Singleton Design Pattern."
The programmer gives the Master a strange looking document with some strange looking Java Code and tells that's how he programmed the Robot.
Realizing the Singleton in Java
And this is what the document read :
public class Egg implements Cloneable { private static volatile Egg egg = null; private String eggName; private Egg() { this.eggName = "Golden Egg"; System.out.println("Master, here is your "+this.eggName+" !"); } public String getEggName(){ return this.eggName; } @Override protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } public static Egg getEgg(){ if(egg==null){ synchronized(Egg.class){ if(egg==null){ egg = new Egg(); } } } return egg; }
Understanding what all these means
That's how you would typically realize a Singleton Design Pattern in Java. But what are the most important
features of the code written above and what does the Master needs to understand about the Robot here :
1. A Singleton class, here our Egg class has private constructor.
2. The singleton Egg Class, implements the Cloneable tag interface.
3. The singleton Egg class overrides the clone() method of the Object class.
4. The clone() method in the singleton Egg class throws a CloneNotSupportedException()
5. The Egg Class has a static instance of itself declared as null.
6. The egg class static instance is marked volatile.
7. The Egg class has a public static getEgg() method to return the egg instance
8. There are two null checks on the Egg instance and one of them is inside a synchronized block.
9. The egg instance is created inside a synchronized block.
Private Constructor
The Egg class constructor is marked private. Why would we need that ? The answer is,
"To defeat instantiation of the Egg Class"
Remember what Mr. Robot said about ONE-OF-A-KIND objects. If we allowed a constructor with a more visible
scope, then the code outside of this class can use the constructor to create another Egg object and that defeats
the purpose of a Singleton. There can be only one Egg object in the Robot, that means a Singleton class can
have ONE AND ONLY ONE instance of it on the JVM heap.
Declaring the constructor private restricts the creation of a Singleton object to only once.
But the constructor is not the only one who does that !
The Egg class object and cloning
The Egg class implements the Cloneable interface which is a marker or a tag interface that tells the JVM
that the Egg class object can be cloned.
And that's a problem ! Why ?
Remember what the Robot said to the Master, that he cannot make an Egg on his own, in other words, he
cannot steal the egg from the Robot and make a clone out of it.
Imagine someone doing this on the Egg object :
Egg egg = egg.getEgg(); Egg eggClone1 = (Egg)egg.clone(); Egg eggClone2 = (Egg)egg.clone();
"Blasphemy !" - Robot
The above code creates 3 objects which is indeed blasphemy ! That means more than one separate
Singleton objects now exist on the JVM heap and that's not Singleton.
What you need is not only a private constructor but also protect cloning of a Singleton instance !
The clone() method that the Egg class overrides from the Object class throws a CloneNotSupported()
exception and that prevents the Singleton from being cloned or have more than ONE instance.
Now, if someone tries to clone the Egg, the Robot yells:
Exception in thread "main" java.lang.CloneNotSupportedException at com.factorydp.demo.singleton.Egg.clone(Egg.java:19) at com.factorydp.demo.singleton.EggRobot.main
Null Static Egg instance and public static getEgg() method
We need to finally get the holy Golden Egg. So, we declare a private static egg instance of the Egg initialize
it to null. We define a public static getEgg() method which gives us a shining Golden Egg.
Note : The Egg instance is static. This is another property of the Singleton class. This says that the egg instance
belongs to the Egg class and not to the Egg object. This means, that the egg instance is a shared
resource and it is shared across all the Egg objects, in this case the ONE Egg Object. This gives
rise to the multi-threaded access of the Egg instance. More on this later.
The public static getEgg() method reminds us of something familiar. Can you remember ? Back in my post on
the Factory Design Pattern, we had the method createYummyProduct().These two methods are similar in
the aspect that both of them produce some Object, be it Chicken or Egg.
And hence we call the Singleton's public static getEgg() method a factory method and since it has static access
we call it a "Static Factory Method".
We are making the Egg instance as null in the first place. This means when the getEgg() method is called for the
first time inside the Robot, it will check for the egg instance on null and create the Egg and return it.
This is called the lazy-initialization of a Singleton !
The things about volatile and synchronized
Imagine the Master, who is now greedy, pressing the getEgg() button on the Robot for two times
consecutively.
What happens ?
The Robot sees this action as two separate requests and initiates two separate calls to the getEgg() method.
This means, internally, two separate call stacks get created to handle these two separate requests.
This implies that two separate threads now have the getEgg() method in their call stack and they try creating
the same static Egg instance object, the shared resource.
Now, what if , while one thread is busy creating the Egg, the other gets busy returning it !
We have got a problem here, because if something goes wrong we get something like this :
The Robot is now in the line of fire. The Master yells and decides to throw him away. Instead of two eggs,
the greedy Master now gets a broken one.
We have to save the poor Robot
The problem is concurrent access on a shared resource, the static Egg instance. The two threads working
here do not actually give two eggs but rather a broken one, because while one thread is creating it, it might
not have finished creating it, the other thread sees the partially created Egg and returns it resulting in
something like that.
In other words, one thread cannot see what the other thread has created.
We need to block one thread while the other is working on the static Egg object. Additionally, we need to
make the threads read the actual value of the Egg instance and not the temporary one. We need to make
them read it from the main memory every time.
In other words, we need to mark the shared resource, the static Egg instance as "volatile" in Java.
private static volatile Egg egg = null;
We are not done yet. We need to block the threads from concurrent access. In other words, we need
to block the threads from creating the Egg at the same time.
We need locking, not on the thread but on the Egg object itself.
We could write the getEgg() method like :
public static synchronized Egg getEgg(){ if(egg==null){ egg = new Egg(); } return egg; }
What we are doing here is, we are using the "synchronized" keyword to lock the method getEgg().
Now imagine what if creating a Golden Egg was not that easy. Imagine, there are lot of other things involved
in creating it. Therefore, not only we are locking the creation part of the Egg, we are locking the entire
method which creates an Egg and also does some other things which are not that critical.
We are locking the entire getEgg() method to allow only one thread at a time to access it and since the
getEgg() method is a static member of the Egg class, we are actually creating a "class-level lock".
But creating a class level lock can be a hit on the performance of the Robot as we are also locking
those sections in the method which might not require thread-safety.
What we need is not a class-level lock, but a object-level lock. We need to lock only the "critical
section" of the method, which is the Egg creation code.
We proceed as :
public static Egg getEgg(){ synchronized(Egg.class) { if(egg==null){ egg = new Egg(); } } return egg; }
What the above code does is, it puts a lock over the Egg object and allows thread A to acquire lock over it and
blocks thread B. Thread A checks whether the Egg is null and if it is, creates it and returns it and releases
the lock on the Egg object. When Thread B gets the lock, it does the same as Thread A.
Thus, the two threads don't do concurrent creation of the Object. Thread A gets the lock, executes the creation
code, exits, releases the lock and then enters Thread B.
So the code inside the synchronized block saves us from entering into a sort of a "race-condition".
But, if we extrapolate further we see, there is an outer if statement wrapping up the synchronized block,
checking the same thing as the if inside the synchronized block, but for a different purpose.
if(egg==null){ synchronized(Egg.class){ if(egg==null){ egg = new Egg(); } } }
Whenever a thread enters the getEgg() method, it encounters the outer if and if an Egg is already there,
it just returns and exits. What this means is that the thread of execution never enters the synchronized
block with the outer if statement in place, when an Egg Object is already created.
The thread, with the outer if in place, doesn't bother whether the Egg is fully created or not. It checks
only for the null and if it seems to it the Egg is there, it just returns it.
Then who does bother ? - The "volatile" keyword.
Since the volatile keyword ensures read from and write to the main memory, it also ensures that
object creation happens before reading the object. It ensures that the thread reads the current
value of the object instead of a stale, cached value.
This way of checking for the value of the object to be created, twice, makes the threads defer object
creation to the highest level of procrastination thus promoting the process of "lazy-initialization"
Since the threads never enter the synchronized block once the outer if says an Egg is there,
we are saving the much-required performance at the cost of synchronization and the method of
acquiring and releasing locks.
And the methodology of designing a Singleton in such a way is known as "double-checked locking of
a Singleton".
Prior to Java 5,using a double-checked locking of a Singleton was heavily discouraged as although the
volatile keyword gives the assurance of happen-before nature of operation, the Java Memory Model
played the spoilsport as it didn't guarantee the order of the reads and writes of volatile variables.
Java 5 and hence, better concurrency paradigms are in place but still the way of doubly checked locking
of a Singleton is heavily discouraged. It makes the Singleton look like an anti-pattern and makes us
heavily dependent on the JVM's nature of handling threads and volatile variables which are often not
guaranteed.
The Master has now reconciled with Mr. Robot and both are happy until one day this happened :
The Robot Programmer Was Fired !
Back at the Robot Programmer's office, they changed their Robot Programming methodology. Although, the Robot Programmer did his job brilliantly making Mr. Robot and his Master live happily thereafter, but he became the Dr. Jekyll and Mr Hyde in the long run. He became the victim of his own code. Even if his code of a doubly-checked locking of the Singleton worked but as I said above, they used
a version older than Java 5, they found out about the pitfalls of the doubly checked locking and they put the code to test. The programmer's code sometimes produced a nice Golden Egg, sometimes a half and it was too tough to test. Those guys adopted the TDD approach, and the
programmer's code gave the team nightmares unit testing it. And they fired the poor programmer.
The Robot Programmer's association upgraded to Java 5 and hired a smart new guy who they thought would save them and he did. The new guy took the old code for Mr. Robot and refactored it to something like below :
public enum GoldenEgg { INSTANCE; }
Whoa ! What did this guy just do with this ? That's like two lines of code from well, like 30 lines of code and we
get a GoldenEgg Singleton by just writing GoldenEgg.INSTANCE;
The power of Enumerations
1. Enums are by default Thread-Safe in Java.
2. Enums are guaranteed to be serialized by the JVM.
3. An Enum Singleton is the best way to write a Singleton in Java 5.
All is fine till now, the Robot got reprogrammed with this Enum and he is producing nice Golden egg for his master
until one day he gets bored and asks his master :
"Master, am I only worth a Golden Egg and nothing else ?"
Master thinks and tells, "You are worth as long as you keep giving me the same Golden egg."
Robot - "But Master, I am bored, I want to produce a Dragon Egg now."
Master - "Yes, but for that I need to throw you away and get a new you again. I can't do that."
Robot - "Master, you don't need to throw me away. Just tell those guys to reprogram me to a Dragon Egg."
The lifetime of a Singleton object
The Singleton Object is created and is ONE-OF-A-KIND on the JVM heap. There are no twins to a Singleton.
And the Singleton object holds the same exact state through out its life cycle. The Singleton's state is
unmodifiable until it is created again with a new state. That means as long as the Robot Application is running,
the Robot will keep on producing the same Golden Egg. That gives us the conclusion :
"A Singleton Object's lifecycle is equal to the lifecycle of the application containing it. When the application
or more specifically, the JVM goes down, the Singleton's state expires with it and it is destroyed."
In other words, a Singleton object exists per application scope in the JVM.
"Master, I think I can give you more than just an Egg" - Robot
We have seen the Singleton Design Pattern, but where in the real world and not in the Robot world, would we use
this pattern, or rather when we should choose this pattern wisely. Here are some true Singleton classics :
1. Loggers and Logging
2. Caching
3. Thread and Database Connection Pooling
4. Registry Settings
5. User Preferences
The Robot had to get himself reprogrammed to produce a Dragon Egg now. But only, Daenerys Targaryen would want
that. We would, however want it to give us sometimes a cached metadata, a pool of database connections and
maintain only ONE Registry.
That's it on the Singleton Design Pattern. I hope you have loved it. It is a lot detailed I think and I hope you didn't get
bored. Post a comment for any thing you feel a Singleton needs to do apart from being the Chosen ONE !