ThreadStatic vs ThreadLocal<T>

Yan Cui

I help clients go faster for less using serverless technologies.

This article is brought to you by

Don’t reinvent the patterns. Catalyst gives you consistent APIs for messaging, data, and workflow with key microservice patterns like circuit-breakers and retries for free.

Try the Catalyst beta

Occasionally you might want to make the value of a static or instance field local to a thread (i.e. each thread holds an independent copy of the field), what you need in this case, is a thread-local storage.

In C#, there are mainly two ways to do this.

ThreadStatic

You can mark a field with the ThreadStatic attribute:

<br />
[ThreadStatic]<br />
public static int _x;<br />
…<br />
Enumerable.Range(1, 10).Select(i =&gt; new Thread(() =&gt; Console.WriteLine(_x++))).ToList()<br />
          .ForEach(t =&gt; t.Start()); // prints 0 ten times<br />

Whilst this is the easiest way to implement thread-local storage in C# it’s important to understand the limitations here:

  • the ThreadStatic attribute doesn’t work with instance fields, it compiles and runs but does nothing..

<br />
[ThreadStatic]<br />
public int _x;<br />
…<br />
Enumerable.Range(1, 10).Select(i =&gt; new Thread(() =&gt; Console.WriteLine(_x++))).ToList()<br />
          .ForEach(t =&gt; t.Start()); // prints 0, 1, 2, … 9<br />
  • field always start with the default value

<br />
[ThreadStatic]<br />
public static int _x = 1;<br />
…<br />
Enumerable.Range(1, 10).Select(i =&gt; new Thread(() =&gt; Console.WriteLine(_x++))).ToList()<br />
          .ForEach(t =&gt; t.Start()); // prints 0 ten times<br />

ThreadLocal<T>

C#  4 has introduced a new class specifically for the thread-local storage of data – the ThreadLocal<T> class:

<br />
private readonly ThreadLocal&lt;int&gt; _localX = new ThreadLocal&lt;int&gt;(() =&gt; 1);<br />
…<br />
Enumerable.Range(1, 10).Select(i =&gt; new Thread(() =&gt; Console.WriteLine(_localX++))).ToList()<br />
          .ForEach(t =&gt; t.Start()); // prints 1 ten times<br />

There are some bonuses to using the ThreadLocal<T> class:

  • values are lazily evaluated, the factory function evaluates on the first call for each thread
  • you have more control over the initialization of the field and is able to initialize the field with a non-default value

Summary

As you can see, using ThreadLocal<T> has some clear advantages over ThreadStatic, though using 4.0 only features like ThreadLocal<T> means you have to target your project at the .Net 4 framework and is therefore not backward compatible with previous versions of the framework.

It’s also worth noting that besides ThreadLocal<T> and ThreadStatic you can also use Thread.GetData and Thread.SetData to fetch and store thread specific data from and to a named LocalDataStoreSlot though this is usually cumbersome…

Whenever you’re ready, here are 3 ways I can help you:

  1. Production-Ready Serverless: Join 20+ AWS Heroes & Community Builders and 1000+ other students in levelling up your serverless game. This is your one-stop shop for quickly levelling up your serverless skills.
  2. I help clients launch product ideas, improve their development processes and upskill their teams. If you’d like to work together, then let’s get in touch.
  3. Join my community on Discord, ask questions, and join the discussion on all things AWS and Serverless.

6 thoughts on “ThreadStatic vs ThreadLocal<T>”

  1. Thank you for your clear explanation.
    One question about 4th block of code. Shouldn’t be _localX.Value++ there?
    With your code compiler says Operator ‘++’ cannot be applied to operand of type ‘System.Threading.ThreadLocal”

    Best regards,
    Grzegorz

  2. Hi,
    What’s with the ‘readonly’ on the
    ‘private readonly ThreadLocal _localX = new ThreadLocal(() => 1);’

Leave a Comment

Your email address will not be published. Required fields are marked *