Thread specific data becomes easier in .NET 4.0 via ThreadLocal<T>

Occasionally, when dealing with multithreaded code, there are uses for data that is kept in a manner that is unique to the currently running thread. This is accomplished via using Thread-local storage. Typically, in .NET 3.5, this was handled via the [ThreadStatic] attribute, however, this puts certain restrictions on usage. The main problem with ThreadStatic is that it is exactly that – static data stored per thread. This can be problematic, especially if you’re using ThreadPool threads, as the data is never released cleanly.

Currently, if you want to use data kept at a local scope with a copy per thread, the solution is to use a LocalDataStoreSlot to manage your threaded data. This works, but is not very developer-friendly. It is not type-safe; all data is stored as a System.Object. It is clunky at best to use, especially if you want to free, as you have to use and track strings with named data slots in order to release the memory. Version 4 of the .NET Framework fixes all of these issues by introducing ThreadLocal<T>.

The new ThreadLocal<T> class provides us with a strongly typed, locally scoped object we can use to setup data that is kept separate for each thread. This allows us to use data stored per thread, without having to introduce static variables into our types. Internally, the ThreadLocal instance will automatically setup the static data, manage its lifetime, do all of the casting to and from our specific type. This makes developing much simpler.

Your results will obviously be different, as the order is somewhat random. (We are multi-threading here!)

Here are a few things to note about this sample and these results:

First, when we create the ThreadLocal<int> instance, we have the option of providing a Func<T> to the ThreadLocal<T>’s Constructor. This allows us to provide an initialization routine which will be used the first time a given thread accesses the Value property. This greatly eases our construction burden, since we can just wrap everything in a delegate (potentially using closures around our class variables) to have complex initialization of our type without having to “think about” it during our work.

Second, when we first access our dataPerThread variable, it is uninitialized. If we need to do complex initialization, we can check the ThreadLocal<T>.IsValueCreated property. This will tell us whether or not a specific value has been created for the currently running thread. When we run the sample, you can see this – the first time a specific thread (the first number, either 9, 10, or 12) accesses dataPerThread, IsValueCreated returns false. When we then read the value, our Func<T> will execute, and set the data to the current managed thread ID. The subsequent times we try to read the data, it’s already been created.

Third, ThreadLocal<T> implements IDisposable. This provides a much simpler way of handling cleanup than trying to deal with static variables per thread.

So the final question I’ll address here: Why is this useful, and where would I want to use this class? In my case, I already have one very good use case. I will be using ThreadLocal<T> in order to handle a thread-specific cache.

We have some algorithms which are parallelizable. However, as we run from one case to the next, there is a chance we can save quite a bit of computation by caching and reusing certain steps, momoizing the results. However, since we’re threading the algorithm, sharing this cache amongst the threads is problematic – it requires adding locking within the algorithm in order to have a thread-safe cache. The locking nearly wipes out the speed gains we achieve via the caching.

By using ThreadLocal<T> to store our cache information, each thread can have it’s own copy of the cache, created once per run (local scope). This provides us with completely threadsafe, lock-free memoization, at the cost of two threads potentially recalculating results. Profiling our algorithm proved that this provided a dramatic speed improvement.

This can be accessed like any other variable. The method in question will need to have some way to access the variable – whether its a ThreadLocal or a normal variable. If you pass a reference to the ThreadLocal to the method, you can use it there directly. Alternatively, you could wrap this in some other class to provide cleaner access, if required.

Excellent article. ThreadLocal is incredibly powerful – it allows you to convert any class that is not thread safe into one that is. Each class runs in its own “sandbox”, the universe of variables that it sees are based on the ThreadID.

I actually manually implemented the effect of ThreadLocal a week ago – its a nice feeling knowing I can use ThreadLocal to replace all of my prior code.

To implement the effect of ThreadLocal yourself, create a wrapper over a non-thread-safe class which uses a dictionary to create a new class instance for each ThreadID (the key for the dictionary is the ThreadID). This means that if one thread is in the middle of doing something, another thread cannot come along and corrupt any class variables (by calling .ResetCounter(), for example).

ThreadLocal is incredibly powerful – it allows you to convert any class that is not thread safe into one that is.

Your article also beats the MSDN one for understandability by an order of magnitude.