ThreadLocal Internal Working

Anmol Sehgal
3 min readNov 25, 2018

--

ThreadLocals are the famous components in any multithreaded environment. To explain it in nutshell, think of them as the medium of providing scope to the variables. As ‘public’ means globally accessible, ‘private’ means accessible only within the class, the ThreadLocal means it is accessible only inside the Thread. What does that mean? Okay, lets clear it. It means if say Thread T1 sets some attribute, say ‘x’(with scope ThreadLocal) then even if it is public, or declared anywhere in the project, only thread T1 can get the value of x. Other threads will get null value of it, as if it never assigned any value. That's the power of ThreadLocal API.

Internal Working of Thread Local

Thoughts before going into the actual implementation:

Basically what it does is, it allows to have independently initialized copy of a variable for each thread i.e. variables mapped to a particular Thread. As you read it correctly, the mapping is done. So, HashMap seems ideal data structure for this use case.
The Thread can be the key(Thread.currentThread() actually), and values can be the attributes.
But if you look into the Java implementation, it's not just hashmaps. Why? What's the problem with this approach?
The basic problem which must come to the mind when talking about hashmap and the multithreaded environment is that Hashmap is not Thread Safe. In Java, we have an alternative to it, called ConcurrentHashMap.
So we are good to go with ConcurrentHashmaps to implement ThreadLocals.
But wait a minute, the java implementation again is not just about the ConcurrentHashmaps. It has WeakReferences and all. Why? Let's give this some thoughts.
What could have been the problems of using merely the ConcurrentHashmaps?
As the Threads are used as Key in the Map, and as the map is never GC’d, the Threads will never be GC’d as we will end up keeping their references forever. This will result in memory leaks.
To solve this, we can use WeakReferences, which means that it will only be non-null until it has any reference to it, or else it will be GC’d.
Another massive problem which is still present is the concurrency issues. Although ConcurrentHashMap with the WeakReferences seems ideal approach, ultimately ConcurrentHashMap still has to deal with preventing multiple threads from messing with it in any way, like if different threads hit it regularly, it will result in slowdowns. This is called Thread contention.
So maybe we need some other way to implement this.

Java implementation:

Java implementation of ThreadLocals is an example of one of the brilliant out-of-the-box thinking. We’ve been thinking of mapping threads to values but actually, it is the mapping of ThreadLocal objects to values in each Thread. If each thread stores the mapping, and ThreadLocal merely provides a nice interface into that mapping, we can avoid all of the issues of the previous implementations. Let's discuss this in details:
We are saying that instead of:
new WeakHashMap<Thread,T>()
we have:
new WeakHashMap<ThreadLocal,T>()in Java.
And the thread itself stores the mappings.

Let's go through the Java Code:

This is the Thread class in Java. It has the Map inside it, where it maps ThreadLocal(as a key) with the values.

Let's look at the set() method implementation:

It sets the current ThreadLocal as the key, with the value mapped to it. And this map is actually inside the Thread:

So basically it gets the ThreadLocal mappings to the values from the Thread(for which the values are related to).

As you can see, it the exact opposite of what we are trying out before. Instead of Thread local having the mapping of Thread-Values, it is the Thread which has mappings of ThreadLocals-values.
ThreadLocal can then get the values for a particular thread by getting the map from that thread, and then getting the MapEntry from that map(pertaining to its own key as an instance), and then getting values from that MapEntry, as:

Building the structure in a reverse manner we have avoided thread contention issues altogether as this ThreadLocal can only access the value in the current thread. Also, when the Thread has finished the work, the map can be garbage-collected, so we have also avoided the memory leak issue. It is one of the great designs in Java.

Please go through https://goo.gl/3yi4G5 to see where did I get the chance to use it in my live project, where Threadlocal was the ideal solution.

--

--