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

一曲冷凌霜 提交于 2019-11-27 03:36:58
Jim Mischel

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>.

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();
    }

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.

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.

I'm using both in the same place because ThreadStatic Initialize only on first thread, ThreadLocal Initialize for each thread.

[ThreadStatic]
    private static IOperationHolder<RequestTelemetry> operation;

    private ThreadLocal<bool> status = new ThreadLocal<bool>(true);

    //TODO: this method will move AOP start method
    public void StartOperation(string functionName)
    {
        RequestTelemetry requestTelemetry = new RequestTelemetry { Name = functionName };
        operation = telemetryClient.StartOperation(requestTelemetry);
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!