MyArchiBook

SINGLETON in Multithreaded Environment

with 12 comments

  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.

Result

Result

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.

 

Written by thangaveluaishwarya

May 24, 2013 at 11:22 PM

12 Responses

Subscribe to comments with RSS.

  1. 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

  2. I wanted this detail and explanation.thank you

    Rohit

    May 26, 2013 at 7:34 AM

  3. 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

  4. Great one!!! Can write more on other patterns?

    Sundar

    May 28, 2013 at 7:59 AM

  5. […] SINGLETON in Multithreaded Environment (aishwaryavaishno.wordpress.com) […]

  6. very few blogs have this clarity. very useful

    Geeky Java

    May 29, 2013 at 10:43 PM

  7. good and very helpful. don’t have to see other sites.

    Ram

    May 31, 2013 at 11:00 PM

  8. Try developing gaming!!!!

    sudarsansrikanth

    July 12, 2013 at 11:21 AM

  9. Thank you so much! took my understanding of Singleton to next level

    Karthik

    September 5, 2014 at 4:08 PM


Leave a reply to Ram Cancel reply