SINGLETON in Multithreaded Environment
Most of the time, we are confined to sequential programming.However,several parts of our program can also be executed parallely by concurrent programming. In concurrent programming, the whole program is split into independent running tasks.Using multithreading, each of these independent tasks (also called subtasks) is driven by a thread of execution.The advantages of concurrency is faster execution,improving code design(espeically in Simulation Applications) etc.,
To be simple, Unless multithreading had been added to Java, any concurrent Java programs wouldn’t have been portable to the Macintosh and similar platforms, thus breaking the “write once/run everywhere” requirement (Eckel,Bruce et al., 2005).
However the real problem with this concurrency occurs, when each of the tasks begin to interfere with eachother.I mean at times,correct programs can also exhibit incorrect behavior.
Let’s see what incorrect behaviour, a Singleton Class can execute in a mutithreaded environment.
I have written the following code with respect to the MusicStore example that I have discussed in my previous blog(https://aishwaryavaishno.wordpress.com/2013/05/17/global-access-point-singleton-design-pattern/).However I have made variations in my Singleton class to signify the importance and disadvantages of each implementation.
private static MusicStre getMusicInstance(){ if(musicInstance==null){ musicInstance=new MusicStore(); } return musicInstance;
- In the above method, the instance is created via Lazy Initialisation.i.e.,the object is created only when needed.
- Lazy Initialisation is usually done for Performance Optimisation.
Here let’s consider that two threads are accessing this class.
The flow goes this way,
- Thread 1 enters the class
- Thread 1 accesses the method getMusicInstance().
- Initially the musicInstance is null , so the control goes inside the if()block to create new Music Instance for the class.
- Consider thread 2 also enters the class parallely with thread 1.Here there are two chances,
Chance 1:Thread 1 completing its process before thread 2 accesses the getMusicInstance method.If so, the musicInstance for thread 2 will not be null.Thread 2 gets the same Instance as Thread 1.
Chance 2: Thread 1 has not yet completed its process(getting Instance). If so, musicInstance for thread 2 will be null.Therefore the thread 2 control goes inside the if()block to create new Music Instance for the class.
Here for Chance 2 the result will be as above.Thread 1 has new Instance and thread 2 also has a new Instance.It’s very obvious from the picture that the MusicStore class(supposed to be a Singleton class) cannot be called a singleton class because it has violated the behaviour by giving different instances.Therefore Thread Safety has not been achieved here.
Let’s see how to achieve Thread-safety.
1.Using Synchronized Block- LAZY Initialization:
The above problem of thread-safety can be achieved by using a Synchronized block.
public static MusicStore getMusicInstance(){ synchronized (MusicStore.class) { if(musicInstance==null){ musicInstance=new MusicStore(); } } return musicInstance; }
Synchronized block allows only one thread to run at a time . The part of method that has to be synchronized is placed inside the block.Here Thread 1 comes in . It acquires the lock. Now the thread 2 has to wait till Thread 1 comes out of the synchronized block and releases the lock.
Here we do synchronisation, to get newMusicInstance object for threads having NULL music Instance.In the above case we can notice that, whether the music Instance of threads is null or not , the thread has to wait. It’s a waste of time for Threads which has musicInstance!=null.
To avoid this we use another null check condition before the synchronized block as shown below.
public static MusicStore getMusicInstance(){ if(musicInstance==null){ synchronized (MusicStore.class) { if(musicInstance==null){ musicInstance=new MusicStore(); } } }return musicInstance; }
FLOW:
- Thread 1 enters the method getMusicInstance(). Here initially musicInstance is null.
- Now Thread 1 enters the synchronised block and acquires the lock. If no thread has passed the synchronized block earlier, the musicInstance of thread 1 still remains null.
- Thread 1 gets the new musicInstance.
- Thread 2 enters the method parallely with the thread 1.(Consider thread 1 has entered the synchronised block and has not finished complete execution)So, the music Instance of thread 2 will also be null.
- Thread 2 tries entering the synchronized block.Since thread 1 has acquired the lock, thread 2 waits till thread 1 completes it’s execution and releases the lock.
- Thread 1 releases the lock
- Thread 2 enters Synchronized block.
- NewMusicInstance got by thread 1. So musicInstance for Thread2!=null.So,thread 2 does not enter into if() block but will get the same instance as Thread 1,thus achieving thread safety.
This process of double checking is called DOUBLE CHECKED LOCKING PATTERN.
Note: Here I have not synchronized the whole method but have synchronized only a part of the code .
Synchronization is useful to control access to resources within the same JVM. If the resources are present in different JVM then synchronized block alone is not sufficient, we will have to get an external lock .
2.Using Lock-LAZY Initialization:
public static MusicStore getMusicInstance(){ final Lock lockObj=new ReentrantLock(); if(musicInstance==null){ lockObj.lock(); if(musicInstance==null){ musicInstance=new MusicStore(); } lockObj.unlock(); } return musicInstance; }
This lock is a mutually Exclusive one(MUTEX).i.e, allows only one thread at a time.
Here the execution is the same as the synchronised method. However,this implemetation can used, when multiple JVM’s come into picture.
3. EAGER Initialisation:
private static final MusicStore musicInstance=new MusicStore(); private MusicStore(){ } public static MusicStore getMusicInstance(){ return musicInstance; }
- Here Instantiation happens once when the class is called.It is a very straight-forward implementation.
- If the object does not cost too high, then this would be a better approach.But when there are situations where, lazy loading is needed, then this approach cannot be used.
Every coin has its two sides.Likewise,all the above types of implementation has it’s own advantages and disadvantages. So,it’s all left upto the developer/designer to choose the right type of implementation based on the needs.
I would also like to add on that, if the proper designing of the Singleton class is not done and is used in applications related to Banking, DB resource sharing etc., then it would for sure cause a disaster.
Life is Simple just because Design is always around but designing that Design Pattern is not that Simple.
For enterprise application a
re you saying its mandatory to add synchronized block everywhere?
I came across your previous post on singeton and it was interesting. You have detailed every usage more than head first.
Swaminathan
May 25, 2013 at 7:04 AM
@Swaminathan : Thanks for your comment.
Ans for ur Question : For an Enterprise Application, there are many factors that have to be considered.
The most important thing one has to consider is that, an Enterprise application will be used by Concurrent Users. Whenever there is a need to create only one instance in JVM, then we go for Singleton pattern.It’s not always mandatory to use synchronised blocks .
A simple usage without synchronized blocks is,
private static final MUSIC_INSTANCE=new MusicStore();
Also have a look at BillPugh’s Theory on Singleton , that’s also another better implementation .
thangaveluaishwarya
May 29, 2013 at 10:47 PM
yes but see this also
http://www.ibm.com/developerworks/java/library/j-dcl/index.html
might be useful too
Geeky Java
May 29, 2013 at 10:50 PM
http://stackoverflow.com/questions/11165852/java-singleton-and-synchronization
Geeky Java
May 29, 2013 at 10:52 PM
I wanted this detail and explanation.thank you
Rohit
May 26, 2013 at 7:34 AM
Before Reading above article I Know only how to synchronize a method.After I gone through the tutorial.I learned how to synchronize particular part of the code..really nice explanation.Thanks for learning-;)
Ganesh
May 26, 2013 at 5:28 PM
Great one!!! Can write more on other patterns?
Sundar
May 28, 2013 at 7:59 AM
[…] SINGLETON in Multithreaded Environment (aishwaryavaishno.wordpress.com) […]
Creating a Thread using C++ Boost Lib. | Khuram Ali
May 29, 2013 at 3:18 PM
very few blogs have this clarity. very useful
Geeky Java
May 29, 2013 at 10:43 PM
good and very helpful. don’t have to see other sites.
Ram
May 31, 2013 at 11:00 PM
Try developing gaming!!!!
sudarsansrikanth
July 12, 2013 at 11:21 AM
Thank you so much! took my understanding of Singleton to next level
Karthik
September 5, 2014 at 4:08 PM