Explaining the ThreadLocal

Introduction to ThreadLocal

Java supports multi threading and provides many high level APIs to avoid running into the issues associated with multi threading. One of the concepts we discussed previously is called synchronization. You can read about synchronization in this blog post.

Here are few scenarios I would like to draw your attention:

Thread Safety – classic case for using ThreadLocal

Not all the classes in the Java library are thread safe, also the user defined classes are mostly not thread safe. At many places on the web you will find posts related ThreadLocal  with one example of SimpleDateFormat class.

It is so because SimpleDateFormat is not thread safe. Hence, if an instance of this class is used in multiple methods (which are not thread safe) then in a multi threaded environment the results might not be correct

Consider the below code :

This is a DateFormatter class which exposes two APIs as mentioned below:

  • getFormattedCurrentDate – formats today’s date in a given format.
  • getFormattedBeginningDate – formats the date 01/01/1970 in a given format. 

Here is an implementation of the DateFormatter which uses a SimpleDateFormat (“MM/dd/yyyy”) . Both the implemented methods use the same instance of the SimpleDateFormat.

We all know that using this code in a single threaded model will work absolutely fine!

Now let us try to simulate a multi threaded scenario, here are two runnable tasks, one which prints the formatted current date and the other which prints the formatted beginning date.

Runnable Task to print the formatted current date

Runnable Task to print the formatted beginning date

Here is the code which starts multiple threads and tries to check if the setup works fine,

The code starts 2000 threads, half with each runnable task. Here is a segment of output from the 2000 lines of the output.

Beginning Date – 01/01/1970
Current Date – 01/17/2016
Beginning Date – 01/01/2016
Current Date – 01/17/1970

Definitely there is something wrong, the current date shows 01/17/1970 and the beginning date shows 01/01/2016.

What exactly is going wrong here?

The code seems logically perfect, because there are many correct lines of output. But there is definitely something going wrong and after a lot of drilling into the code, and running it multiple times, I realized that the multiple threads are messing up.

As SimpleDateFormat is not a thread safe class, the format method inside the class can be invoked by multiple threads on the same instance of SimpleDateFormat at the same time. And the code in the format method works on indices of the parsed string, and hence many the threads changing it at the same time, just mingled both the results.

Simple Solution

A very simple solution would be to bring the SimpleDateFormat sdf variable inside the two formatting methods  getFormattedCurrentDate and getFormattedBeginningDate.

Once the variable is moved in, it becomes local to the method and hence, there will be no problem with the thread safety aspect in multi threaded environment.

This looks viable solution except for just one problem. Most of the times, there will be situations such that we will need the instance of SimpleDateFormat in consecutive methods in the same thread. If we have this instance as a local variable in a method, we will have to make it available to subsequent methods by the following two ways:

  • Declaring a local variable in each of the methods
  • Passing the local variable as argument to each of the methods

Both are cumbersome, and requires un-necessary extra lines of code, which in turn increases possibilities of new bugs. Hence, the language provides the ThreadLocal construct.

What is ThreadLocal?

ThreadLocal is a generic construct, a variable of type ThreadLocal can be declared in any class.

If there are multiple threads executing a method which refers to the variable of type ThreadLocal, then each thread will have its own independently initialized copy of the variable.

This is clearly different than the normal variables, where each thread accesses the same copy of the variable declared in the class.

Here, is the above code using ThreadLocal

The new formatter has a private static variable of type ThreadLocal<SimpleDateFormat> and every time a thread needs to access the variable sdfTL it will get its own copy.

I ran the same program again with the new formatter and the results were all correct.

Beginning Date – 01/01/1970
Current Date – 01/17/2016
Beginning Date – 01/01/1970
Current Date – 01/17/2016

Advantages of ThreadLocal

Thread Safety to unsafe libraries

As we saw above, thread safety is a major concern, wrapping a non thread safe class in a ThreadLocal will help ensure correct results.

You can consider thread local as a wall built around an object which shields the object from other threads.

Ease of access

As ThreadLocal variable is owned by a thread, any code which is executed by this thread can access the values stored using the ThreadLocal without explicitly passing them

Drawbacks of ThreadLocal

Memory Leaks

As we see, the thread local creates one instance of SimpleDateFormat for each of the threads. Now, in a thread pooled environment, if the thread local is not cleaned by calling its remove method, it will never allow the SimpleDateFormat to be garbage collected and that will end up having a lot of unused instances of SimpleDateFormat.

If these kinds of error occur, they will unnecessarily project a OutOfMemoryError even if your application is not using all the memory.

Unexpected Dependencies

Now, that few of the layers in our application rely of the values stored in the ThreadLocal. Not every parameter passes through the method invocation chain and assumes certain values from the ThreadLocal.

This is against the principles of good architecture, I mean after so much of design discussions and architecture crafting if we still violate the Abstraction and Encapsulation principles, there is certainly something wrong.

Lesson Learnt

ThreadLocal eases a lot of problems and is a magnificent concept, however few evils are associated with it and it requires a lot of precision and careful crafting before you can use the ThreadLocal.

The advice is, when you have thread pools and ThreadLocal together, be extra cautious.

Conclusion

We understood the concept of ThreadLocal with a great example. We also learnt about the pros and cons of the ThreadLocal construct.

But the discussion is yet not complete, in the next post we will discuss another very important use case of ThreadLocal which is Authentication.

In another post, we will dissect the ThreadLocal implementation of Java.

Stay Connected and Stay Subscribed…