locked
ThreadLocal<T> vis-à-vis ThreadStatic RRS feed

  • Question

  • Hi C# folks,

    Can you please elucidate the advantage of ThreadLocal<T> vis-à-vis ThreadStatic with example.

    BTW, is ThreadLocal<T> best suited for Windows 8 Store App rather than traditional desktop application viz., on Windows 7?

    Welcome roses and brickbats, shoot!

    Thanks

    Thursday, July 17, 2014 10:11 PM

Answers

  • Hi ,

    There is a good sample as below

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

    You can check Thread­Sta­tic attribute.

    ThreadLocal<T>

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

    [ThreadStatic] doesn't automatically initialize things for every thread.

    ThreadStatic]
    private int Foo = 42;

    The first thread that uses this will see Foo initialized to 42. But subsequent threads will not. The initializer works for the first thread only. So you end up having to write code to check if it's initialized.

    ThreadLocal<T> solves that problem by letting you supply an initialization function. that's run before the first time the item is accessed.

    Sum­mary

    As you can see, using ThreadLocal<T> has some clear advan­tages over Thread­Sta­tic,

    Have a nice day!

    Kristin

    • Marked as answer by Fred Bao Monday, July 28, 2014 8:45 AM
    Friday, July 18, 2014 7:55 AM
  • In short, ThreadLocal<T> is more flexible and safer to use than [ThreadStatic].

    ThreadStatic can only be used on static fields and those fields cannot be initialized. What's worse is that these restrictions aren't enforced in any way. For example, you can place [ThreadStatic] on a non-static field and the code compiles and runs but the attribute will have no effect.

    • Marked as answer by Fred Bao Monday, July 28, 2014 8:45 AM
    Friday, July 18, 2014 2:17 AM

All replies

  • In short, ThreadLocal<T> is more flexible and safer to use than [ThreadStatic].

    ThreadStatic can only be used on static fields and those fields cannot be initialized. What's worse is that these restrictions aren't enforced in any way. For example, you can place [ThreadStatic] on a non-static field and the code compiles and runs but the attribute will have no effect.

    • Marked as answer by Fred Bao Monday, July 28, 2014 8:45 AM
    Friday, July 18, 2014 2:17 AM
  • Hi ,

    There is a good sample as below

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

    You can check Thread­Sta­tic attribute.

    ThreadLocal<T>

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

    [ThreadStatic] doesn't automatically initialize things for every thread.

    ThreadStatic]
    private int Foo = 42;

    The first thread that uses this will see Foo initialized to 42. But subsequent threads will not. The initializer works for the first thread only. So you end up having to write code to check if it's initialized.

    ThreadLocal<T> solves that problem by letting you supply an initialization function. that's run before the first time the item is accessed.

    Sum­mary

    As you can see, using ThreadLocal<T> has some clear advan­tages over Thread­Sta­tic,

    Have a nice day!

    Kristin

    • Marked as answer by Fred Bao Monday, July 28, 2014 8:45 AM
    Friday, July 18, 2014 7:55 AM