NET问答: ThreadStatic 和 ThreadLocal<T> 哪一个更好 ?

咨询区

  • user2341923

[ThreadStatic] 被设计成特性, ThreadLocal<T> 被设计成泛型,为什么会有这两种设计方案呢 ?谁能告诉我他们的优缺点各是什么?是不是泛型的方式更好一点?

回答区

  • Sanjeev

[ThreadStatic] 背后的运作思路是为每个线程都copy一份变量的一个副本,参考如下代码:


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

从上面的代码片段可以看出:每个线程都有一个 value 的初始化副本,除了创建它的主线程。

如果你想对所有线程一视同仁或者有自己的初始化逻辑,这时候就可以用 ThreadLocal 了。

  • marai

ThreadStatic 只会在创建它的线程中保留赋值,而 ThreadLocal 会将此赋值保留在所有线程中,比如我的简单测试代码。


    class Program
    {
        public static ThreadLocal<int> _threadlocal = new ThreadLocal<int>(() => 10);

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

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

            Console.ReadKey();
        }
    }

点评区

个人感觉 ThreadStatic 和 ThreadLocal 相比,前者算是一个简单粗暴的版本,同时在用 ThreadStatic 时也要了解容易踩到的坑,比如 Sanjeev 大佬的例子中所述:value = 10 只会在创建它的线程中被保留,在其他线程中会被默认为初始值,如:value=0

如果你想高度的定制化,可以采用 ThreadLocal ,毕竟你看那些链式跟踪的框架都少不了它的踪影。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#中的Attribute是一种可用于为程序元素(如类、方法、属性等)添加元数据的标记。它们可以用来提供信息,例如代码中的注释、编译器指令、运行时行为等。 以下是C#中常用的Attribute用法大全: 1. [Obsolete]:表示代码已过时,不应再使用。 2. [Serializable]:指示该类可以被序列化为二进制流,可以保存到文件或数据库中。 3. [DataContract]:用于指示该类可用于数据序列化,例如在Web服务中使用。 4. [DataMember]:用于标记序列化的数据成员。 5. [XmlRoot]:用于指示XML序列化时的根元素名称。 6. [XmlType]:用于指示XML序列化时的类型名称。 7. [XmlIgnore]:用于指示在XML序列化时忽略某个属性或字段。 8. [DllImport]:用于指示在C#中使用外部函数库。 9. [Conditional]:用于指示当某个条件为真时才编译特定的代码。 10. [MethodImpl]:用于指示方法的实现方式,例如是否为内联函数。 11. [ThreadStatic]:用于指示某个静态字段是线程本地的,每个线程都有自己的副本。 12. [AttributeUsage]:用于指示Attribute的使用方式和目标。 13. [CLSCompliant]:用于指示该代码符合公共语言规范。 14. [Conditional("DEBUG")]:用于指示只在调试模式下编译特定的代码。 15. [DebuggerStepThrough]:用于指示调试器不要在该方法中断。 16. [DefaultMember]:用于指示该类的默认成员,例如在集合类中,可以通过索引访问元素。 17. [DefaultValue]:用于指示某个成员的默认值。 18. [Description]:用于指示某个成员的说明文本,在属性窗口中显示。 19. [DisplayName]:用于指示某个成员的显示名称,在属性窗口中显示。 20. [EditorBrowsable]:用于指示某个成员是否在属性窗口中可见。 21. [Obsolete("message")]:用于指示代码已过时,提供一条说明信息。 22. [SerializableAttribute]:用于标记可以序列化的类。 23. [NonSerialized]:用于标记不需要序列化的字段。 24. [XmlArray]:用于指示序列化为XML时的数组名称。 25. [XmlArrayItem]:用于指示序列化为XML时的数组元素名称。 26. [XmlEnum]:用于指示序列化为XML时的枚举名称。 27. [XmlInclude]:用于指示序列化为XML时包含某些类型。 28. [XmlElement]:用于指示序列化为XML时的元素名称。 29. [XmlAttribute]:用于指示序列化为XML时的属性名称。 30. [Serializable]:用于标记可序列化的类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值