Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ThreadStatic v.s. ThreadLocal<T>: is generic better than attribute?

[ThreadStatic] is defined using attribute while ThreadLocal<T> uses generic. Why different design solutions were chosen? What are the advantages and disadvantages of using generic over attributes in this case?

like image 998
user2341923 Avatar asked Aug 20 '13 11:08

user2341923


People also ask

What is Threadstatic?

The ThreadStaticAttribute makes a field thread-local. This means that every thread has its own reference corresponding to the field. Fields marked with ThreadStaticAttribute must be static and not initialized statically. This attribute does not affect instance fields.

What is Threadlocal in C#?

Thread-local storage (TLS) is a computer programming method that uses static or global memory local to a thread. All threads of a process share the virtual address space of the process. The local variables of a function are unique to each thread that runs the function.

Are local variables thread safe in C#?

Thread-local storage: Variables are localized so that each thread has its own private copy. These variables are thread-safe since they are local to each thread.


3 Answers

Something the blog post noted in the comments doesn't make explicit, but I find to be very important, is that [ThreadStatic] doesn't automatically initialize things for every thread. For example, say you have this:

[ThreadStatic]
private static 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 (as Reed's blog shows) that's run before the first time the item is accessed.

In my opinion, there is no advantage to using [ThreadStatic] instead of ThreadLocal<T>.

like image 75
Jim Mischel Avatar answered Oct 16 '22 01:10

Jim Mischel


ThreadStatic Initialize only on first thread, ThreadLocal Initialize for each thread. Below is the simple demonstration:

    public static ThreadLocal<int> _threadlocal =
        new ThreadLocal<int>(() =>
        {
            return Thread.CurrentThread.ManagedThreadId;
        });

    public static void Main()
    {
        new Thread(() =>
        {
            for (int x = 0; x < _threadlocal.Value; x++)
            {
                Console.WriteLine("First Thread: {0}", x);
            }
        }).Start();

        new Thread(() =>
        {
            for (int x = 0; x < _threadlocal.Value; x++)
            {
                Console.WriteLine("Second Thread: {0}", x);
            }
        }).Start();

        Console.ReadKey();
    }

enter image description here

like image 37
marai Avatar answered Oct 15 '22 23:10

marai


The main idea behind ThreadStatic is to maintain a separate copy of the variable for each thread.

class Program
    {
        [ThreadStatic]
        static int value = 10;

        static void Main(string[] args)
        {
            value = 25;

            Task t1 = Task.Run(() =>
            {
                value++;
                Console.WriteLine("T1: " + value);
            });
            Task t2 = Task.Run(() =>
            {
                value++;
                Console.WriteLine("T2: " + value);
            });
            Task t3 = Task.Run(() =>
            {
                value++;
                Console.WriteLine("T3: " + value);
            });

            Console.WriteLine("Main Thread : " + value);

            Task.WaitAll(t1, t2, t3);
            Console.ReadKey();
        }
    }

In the above snippet, we have a separate copy of value for each thread, including the main thread.

enter image description here

So, a ThreadStatic variable will be initialized to its default value on other threads except the thread on which it is created.

If we want to initialize the variable on each thread in our own way, use ThreadLocal.

like image 16
CSR Avatar answered Oct 15 '22 23:10

CSR