Singleton Threads

My wife and I enjoy cooking and of course eating the food we prepare. Yesterday we decided to making from scratch empanadas. Different cultures around the world have come up with similar implementations. I am not a historian so I am not sure if all foods covered in some type of dough and then baked or deep fried, are derived from a single version or instance (the Computer Science shows up).

In the US we refer to a similar object with the name turnover. My wife’s family comes from Spain. According to this article the name empanada was mentioned in a book published in Catalan as early as 1520. It seems that one should be able to find the best recipes for empanadas in and around Barcelona. Next time we are in that area will make sure to have some empanadas.

My parents came from Italy. As a matter of fact I am first generation not born in Genoa.  In Italy there are similar foods named calzone and Stromboli both of which we had on my parents table quite often while growing up.

While searching the web with Chrome, I found this site which lists some foods related to empanadas. Empanadas enclose some type of food in dough while a food that is quite common in the US, presents the food in an open face version. That is what pizzas are all about. You can read more about pizza here. The modern pizza was created in Napoli, Italy, and yes my wife and I have been to the restaurant that claims to have created the Neapolitan pizza.

So back to yesterday, my wife made about seven pounds of empanada stuffing (beef, onions, eggs, garlic, and many other spices). I made a batch of dough (flour, yeast, olive oil, and a few more ingredients) which was enough to make about 18 empanadas. While we were preparing the food, one of my wife’s nice stopped by. Apparently she was interested in joining us for lunch. While we were chatting, my son calls. One thing and the other and he (plus wife and two sons) requested some empanadas for Sunday. We where forgetting that two of my in-laws and spouses were stopping by around 02:00 PM for lunch.

Panic mode set in. We had plenty of stuffing, but not enough dough. I made a second batch. As the empanadas were taking shape, I made a third batch. Of course the dough did not have enough time to rise, but it had to be done. When all was set and done, we ended with around six dozen empanadas. We were baking them in batches so things were moving along.

Our formal guests arrived so we all had empanadas with lime, beer, and wine. On Friday, my wife had prepared a couple gypsy arms stuffed with “dulce de leche”. We forgot to serve the salad but I had more than enough to eat and drink. We did not have a chance to walk outside yesterday. That said; I checked my fitbit before going to bed. I had about 10,500 steps. I was pleasantly surprised with the final tally.

Today we are going out for Chinese food. We do not wish to cook.

OK, enough of chitchat. Let’s see if I can remember the main topic for this post. For starters, please take a look at the Singleton Pattern post. As you can see, the Singleton class is a textbook implementation. You can find it in any object oriented design book and website.

Now let’s take a look at some edited output captured from the console of my Eclipse IDE:

hashCode: 292567422     <=== first instantiation
val: 3
hashCode: 1727020675    <=== second instantiation
val: 3
val: 4
hashCode: 1727020675    <=== third instantiation
val: 1
val: 2
val: 6
val: 5
val: 4
val: 4
val: 2
val: 8
val: 7
val: 9
val: 10
val: 11
val: 12
val: 13
val: 14
val: 15
val: 17
val: 16

val: 18

As we will see in the Java code for the implementation of the Singleton class, the getInstance() method seems to have instantiated three different classes. Could this be possible? Let’s see if we can determine this.

The code for the Singleton class follows:

package threads.singleton.canessa;

import java.util.concurrent.Semaphore;

/*
 * Typical Singleton implementation
 */
public class Singleton {
	
	// **** members ****
	private static 	Singleton 	singleInstance = null;
	
	private	static	Semaphore	sem = new Semaphore(1);

	public 			int 		val = 0;
	
	// **** constructor ****
	private Singleton() {
		val = 0;
	}
	
	// **** get instance of this class ****
	public static Singleton getInstance() {
				
		// **** request access ****
		try {
			sem.acquire();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		// **** instantiate this class (if needed) ****
		if (singleInstance == null) {
			
			// **** instantiate Singleton ****
			singleInstance = new Singleton();
			
			// **** inform user what is going on ****
			System.out.println("hashCode: " + singleInstance.hashCode());
		}
		
		// **** release access ****
		sem.release();

		// **** return this class ****
		return singleInstance;
	}

}

The getInstance() method checks if the singleInstance variable is null. If the variable is null, then it instantiates a new Singleton object. The hash code of the object is then displayed. The object is then returned. As we saw in the screen capture, three objects were instantiated for the Singleton class.

Let’s take a look at the test scaffolding implemented in the main() method of the Solution class:

	public static void main(String[] args) {
		
		final int LOOPS = 7;
		
		// **** loop starting threads ****
		for (int i = 0; i < LOOPS; i++) {
			
			// **** create child thread ****
			ChildThread ct1 = new ChildThread();
			
			// **** create second child thread ****
			ChildThread ct2 = new ChildThread();
			
			// **** create third child thred ****
			ChildThread ct3 = new ChildThread();
			
			// **** start first thread ****
			ct1.start();
			
			// **** start second thread ****
			ct2.start();
			
			// **** start third thread ****
			ct3.start();			
		}
		
		// **** ****
		try {
			Thread.sleep(100);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		System.out.println();
		
		// **** create fourth thread ****
		ChildThread ct4 = new ChildThread();
		
		// **** start fourth thread ****
		ct4.start();
		
		// **** wait for thread to exit ****
		while (!ct4.isAlive()) {
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}

We are going to loop 7 times. Each time we instantiate 3 threads using the same class. We then start the 3 threads. In total we run 3 * 7 = 21 threads so far. After the loop, we instantiate 1 more thread and start it once. We end up with 3 * 7 + 1 = 22 thread executions.

Now let’s take a look at the ChildThread class:

package threads.singleton.canessa;

/*
 * 
 */
public class ChildThread extends Thread {

	@Override
	public void run() {
		
		// **** instantiate our Singleton class ****
		Singleton s = Singleton.getInstance();
		
		// **** increment the variable in the class ****
		s.val = s.val + 1;
		
		// **** display the updated value ****
		System.out.println("val: " + s.val);
		
	}
}

The code first instantiates a Singleton object. We should always get the same Singleton object. Once we get the object we increment the val variable by one. We display the value of the variable after we have incremented it. As we can tell by the Singleton class implementation the variable is set to 0 in the constructor. We ran 22 threads. Each thread run incremented the variable by 1. The expected result should be 22. What happened?

Before we dive into determining what happened, let me show a different run of the same program:

val: 5
val: 5
val: 5
val: 5
hashCode: 1727020675
val: 5
val: 8
val: 8
val: 6
val: 9
val: 10
val: 13
val: 13
val: 14
val: 11
val: 15
val: 16
val: 17
val: 18
val: 19
val: 20
val: 21

val: 22

The output by the getInstance() method, out of order due to the display mechanism, only showed once. As you can see the final value for the variable was as expected 22. All went well. So what happened in the previous run? Before we figure it out, if you ran the code several times, it seems to work sometimes while others not. The issue is intermittent and possibly hard to find. In our example it is simple because we have very few lines of code and the sample code was written to bring up the issue.

We instantiate and then start three threads using the same code. The issue is not with the start but with the instantiation. Computers give the impression that they are running a single program. As we know that is not the case. Any program may at any time be interrupted by the OS and a different one may be started. Depending on the OS and priority assigned to a thread, this may happen every few milliseconds.

When the first instance is instantiated, and the getInstance() method has determined that the singleInstance is null so it needs to execute the instantiation of the Singleton class, the thread swapped by the second one. It proceeds to around the same point and decides it has to instantiate a new object. The same seems to occur with the last thread. In this case it seems that three objects were instantiated.

This is something that may or may not happen in your code. If multiple programs or threads are not contending for the Singleton object, then all is well. You got lucky. If there is a resource contention then your program / application / service will work most of the time. To address it we could declare a mutex and use it to protect the creation of the Singleton object.

There are different approaches you could implement based on the services and features offered by your host OS. For example in Windows you can make use of a global mutex. I have used it in production on multiple occasions. I had three different services and they all needed to run single instances so each server made use of a dedicated global mutex.

On a Linux or UNIX platform you can use a file. In a nutshell you create a file with exclusive access. The first request gets access and may instantiate the software. Future requests are rejected as long as the file is opened. Depending on the requirements, you might need to add functionality to check if the software dies / stopped without closing the file.

If you are interested in looking at the entire code, you can find it on my GitHub repository.

If you have comments or questions regarding this or any other post in this blog or if you would like for me to help out on any aspect of the SDLC of a product or service, please do not hesitate and leave me a note below. Requests for help will not be made public.

Keep on reading and experimenting. It is the best way to learn!

John

Follow me on Twitter:  @john_canessa

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.