The Pitfalls of Singleton Design Pattern

Yes! its true that a Singleton object is the loneliest construct in Programming. ūüôā Let us keep the humor aside and listen to this interesting story.

Last time we had a fun story while understanding the Factory Method Design Pattern. This time let us have a story from one of our software developers  Manish. He wants to create this wonderful application.

An awesome application

This application uses the socket connections heavily and has to write data over the network. Manish wrote a code which works great. Every time he wants to use the connection he creates one and starts using it. In no time the application was a hit and people started using his hosted version of the application and the load increased.

As the load started increasing, the application intermittently started throwing exceptions “Cannot open socket connection” or ” No connections available”. And we all know these intermittent errors of so nasty, it is so tough to debug these errors and fix them. Manish spent a day and was able to figure out, what was going wrong.

He noticed the following points:

  1. Connection creation takes a lot of time.
  2. Everyone is trying to create a connection.
  3. With more load, the number of connections created is much more.
  4. The host doesn’t support so many connections.

He understood that he needs to improve his system and must bring in a connection pool to manage all the connections. He will easily solve the problems using a connection pool. The properties of the connection pool is mentioned below:

  1. It has a pool of already created connections (say 100). The maximum number of connections allowed by a host.
  2. The pool manages the life cycle of the connection.
  3. No one will create connections themselves and ask the pool for a connection.
  4. If the pool has any free connection it will offer them one else it will ask them to wait.
  5. After completing their job, the clients will return back the connection to the pool.

With all this setup, now Manish thinks that he has solved the problem and he can be back in business.

The problem with having multiple instances?

It definitely was an improvement over the existing setup and helped a lot. But there was a flaw, now everyone started creating instance of this Connection Pool of their own and hence, the purpose was defied. As every connection pool was entitled to have 100 connections. With many connection pool, it went back to the first situation where clients see that their connection pool still has free connection but the host is still not allowing them to connect.

The Singleton Design Pattern

Now, Manish has to give some more thoughts and make it better. And he knows that he can do that if he can restrict clients from creating their own instances of the Connection Pool. He understood that there has to be just one instance of the connection pool. He figured out a way by declaring the constructor of the Connection Pool private. This puts a check on the clients and they are not able to instantiate the connection pool themselves.

But the problem now is that there exists no instance of the Connection Pool in the application, hence it is rendered useless. Manish decided to create one instance of this pool himself and expose it using a method which is accessible to the client.

Here are the list of changes:

  1. As the constructor is private, this means that the instance has to be created from inside the pool.
  2. Also it cannot be exposed by an instance method. This is because, the client yet doesn’t has an instance to invoke this method.
  3. Hence, the instance has to be exposed using a static method or class method.
  4. This also means that the reference variable for instance has to be static. Because static methods cannot access non static references.

This is how the new class looks like.

Instance Creation by Eager Initialization and its pitfalls

Notice that the instance is eagerly created when the class is loaded in JVM by the class loader. The JVM will make sure that no two threads can access the same class until it has been completely instantiated. But even in this case, if there are multiple class loaders then there is a possibility that two versions of the Pool exists in the JVM and the purpose of singleton again is defied.

Also, if the initialization process does a lot of work and takes a lot of time, the application will take a lot of time to boot up.

Consider if there are many singletons in an application, the eager initialization will require a lot of memory at the boot up, which is not advisable as well.

Manish realized this and tried to fix it by changing it to Lazy Initialization.

Instance Creation by Lazy Initialization

This will fix most of the problems posed by eager initialization.

Now the boot up time is minimized because no instance creation or initialization happens in the beginning. Also, the memory requirement at the startup is minimized.

Here is the code for lazy initialization

Notice that the initialization code has been moved to the static method. Now this is a perfect system, no client can create any instance and can obtain the same instance every time they want one. This works flawlessly.

But not for a long time, while analyzing the logs Manish realized that there are two instances of the Connection Pool which is strange, as he made it flawless and never expected it.  After digging for some more time, he saw that the two Connection Pool instances were created by two different threads and both the threads created them at the same time approximately.

And this explains a lot, if the initialization code of  Connection Pool does a lot of job and takes time, then there is a possibility that the second thread also starts creating another instance of the Pool and hence there can be two pools.

Please Note : This was never a problem in eager initialization, JVM took care of not allowing any thread to access the instance of the Connection Pool until the instance was fully initialized.

Handling Multi Threaded Scenarios

Manish immediately got the solution to this problem, and he knew that he can fix it using synchronizing the getInstance() static method. He was right, and the logs now show just one instance over a period of 2-3 and many more weeks. Here is his new code now.

Side effects of Synchronization

But again, as we know that problems never get over, Manish received complains from his clients. They are experiencing a delay in getting the instance  of the pool now and the delay is significant around 100 times. Manish always knew that their will be a delay due synchronization but 100 times for each client was like too much, it would not be a good thing for the long run.

By closely observing the code he realized that for every invocation from the client, the thread enters in the synchronized block, hence it takes a lot of time as synchronization is a complex and time consuming process. But this is not what he wanted, the only reason he had to make the method synchronized was for preventing duplicate instance creation by different threads. Which means, once the instance is created he ideally does not need the synchronization part.

He thought of an intelligent idea for fixing this which is defined below:

Double Check Locking

He moved the instance creation code to a synchronized block instead of making the whole method synchronized. If there is no instance, synchronized block will be executed else no synchronization is needed as shown below. This is called Double Check Locking or DCL. Here is another good post about DCL 

Notice that he made the uniqueInstance variable volatile. This is required because if the variable is not volatile, it might not communicate its correct state when accessed very frequently from many threads. Check the documentation for volatile to understand this decision.

Is that all?
Is he good with this code?

Looks like YES, he will not face any problems here, until someone uses reflection and breaks the private constructor ūüôā

Get the complete code on github

Conclusion

Now we know why it is important to have Singleton objects and we also know that Singleton Pattern is the Creational Design Pattern which helps in ensuring a unique instance of a given object. Thread Pools and Connection Pools are good example of using Singleton Pattern.

Please let me know in comments if you want more clarifications on the design pattern.

Stay Connected and Stay Subscribed.