Singleton Pattern – Creational

2018-06-21

Reading Time: ~ 5minutes

The Singleton Pattern

Let’s have a chat about the Singleton Pattern. One of the most known and (mis?)used patterns out there. The Singleton Pattern is relatively straightforward and easy to implement. It is both its strength and where the problems appear. We will also show a couple of examples or where you can find the pattern implemented.

Usage

You want to make use of the singleton pattern in cases where:

A single point of truth of your state is desired/required

You need a globally accessible and unique object

Have it initialized only when it is first used

You might be scratching your head for examples on when you’d desire these right now. So here are a couple for you:

Imagine that in a network you have several printers connected to deal with a huge amount of prints that get done. You may have already seen this on a student center where, for example, you click to print and it will get printed on one of several printers, which the system might have informed you or you, most likely, need to hunt down.
Now, in that case, we want to have a single entity that manages the documents to print. This will take care of dispatching the files to the printers, and thus guarantee nothing is printed twice, that the pages are sequentially instead of mixed with other docs, etc. That entity is a singleton.

Another example is one that requires for example to hold the total result of something: from the total in a game where the player is collecting points in each phase or even the total of a survey or pooling done by a system.

Structure of the Singleton Pattern

The structure for this pattern is probably the simplest of all:

Participants

The singleton has the following:

private constructor so that no one can generate copies of it. The process is controlled inside

a private variable (the instance variable) that is used to store the reference to the singleton once it is initialized and to be returned when asked by other components

a public method (getInstance() method) that gives access to the singleton object and is responsible for its initialization or return of the already created reference.

Code Example(s)

The initial approach

This code works for all that matters. You get the singleton you initialized as a static member of the class and you cannot create other copies due to the private constructor. However this is not lazy loaded. So we might have initialized it (and maybe a bunch of other resources it needs) and it never gets used. But blocks the resources it is using until the program gets terminated.

Now, this is already an improvement! We have now lazy initialization and this would work out wonderfully… that is, if the usage is in a single-threaded environment. As you may recall from the post about threads, the threads share some resources between each other and they also do their work only when they receive CPU-time from the scheduler. That can lead to some problems and in this case to have two instances of the Singleton!!!

How? Imagine one thread gets to the check if the instance is null. It figures out it is, but before it can go to the next line, the Scheduler says: “You’ve got enough time, let’s give someone else a go!”. Now another thread gets to the check and the instance is still null. The first thread never got to the initialization part. Now next time these threads get some time, they will go on to both initialize the Singleton

What we can do is a double check with a Synchronized block. The synchronized block will guarantee that only one thread can be inside it at one point. Even if more than one gets to that spot at the same time they will have to wait if the block is already being used by another.

Why the double check though? Why don’t we add the synchronized keyword, before the first null check? As a matter of fact why we don’t add it to the function? Well, the thing is, these synchronized blocks are really expensive for a multithreaded environment, so we try to minimize the scope on which is used. If it was above the first null check or even on the method it would run every time, even after the instance was initialized, making a less than ideal use of resources. Let’s show the best way though:

This implementation is very similar to the one before, with one minor change: we’ve added the volatile keyword to our instance. This is actually to solve a very elusive problem that might occur in java. Java allows for the passing of references for partially constructed objects to be made. This can lead to problems even on the synchronized version.

Since Java1.5 the problem was fixed with the usage of the volatile keyword. With it we tell the compiler that the variable may change between access and thus it should not be optimized any further. This guarantees a perfect singleton 🙂

You can read more about why this is the best way and about the discussion we had before, by going to the wiki page about “Double Checked Locking“.

The Java Interesting Fact

Finally, although I believe it should not be done, i.e. I see it as a bad practice. One can use ENUMS as singletons. In Java, ENUMS are guaranteed by the compiler to be singletons and thus one could use it for it.

Although it can be done, Ireinstatee that I do not support this implementation and as such, I won’t provide a code example for it.

Caveats

Not all is unicorns and rainbows, so here are some of the problems with the Singleton Pattern:

Violates Single Responsibility Principle.

Masks bad design.

Requires special treatment in a multithreaded environment.

Requires endless mocking in unit tests.

There is also a lot of people that actually consider it an anti-pattern, so you might encounter some people that disagree with its implementation.

In the wild (where to find it)

As I’ve promised I’d like to close the discussion with some examples of where singletons can be found:

Many logging implementations make use of a LogManager to hold its configuration. This is a singleton. The usage of Logger is also another example

Java has only one instance of java.lang.Runtime

They are used in OS for services such as the File Manager or the WindowManager