ThreadStatic,ThreadLocal,GetData相比为线程创建对象实例有什么优势?

时间:2014-07-09 10:38:54

标签: c# .net multithreading

一位朋友问我哪个更好ThreadStatic或ThreadLocal。检查文档我告诉他ThreadLocal看起来更方便,从.NET 4.0开始可用,但我不明白为什么使用它们中的任何一个而不是为线程创建对象实例。它们的目的是存储“线程本地数据”,因此您可以不那么笨拙地调用方法,并避免在某些情况下锁定。当我想要这样的线程本地数据时,我总是创建类似的东西:

    class ThreadHandler
    {
        SomeClass A;

        public ThreadHandler(SomeClass A)
        {
            this.A = A;
        }

        public void Worker()
        {
        }
    }

如果我想要火,忘记线程,那将是新的Thread(新的ThreadHandler(新的SomeClass())。TheWorkerMethod).Start(),如果我想跟踪线程,它可以添加到集合中,如果我想跟踪数据ThreadHandler可以添加到集合中,如果我想处理两者我可以为ThreadHandler创建Thread属性并将ThreadHandler放到集合中,我想要threadpool它的QueueUserWorkItem而不是新的Thread()。如果范围很简单,它简短而简单,但如果范围变宽则可以轻松扩展。

当我试图谷歌为什么在对象实例上使用ThreadLocal时,我的所有搜索最终都解释了ThreadLocal是如何比ThreadStatic大得多的,在我看来,人们解释说他们有这个笨拙的螺丝刀,但现在工具箱有重型猴子扳手,更方便锤击钉子。虽然工具箱开始使用锤子。

我理解我错过了什么,因为如果ThreadStatic / ThreadLocal没有优势,他们就不会存在。有人可以指出ThreadLocal的至少一个重要优势是为线程创建一个对象实例吗?

UPD:看起来像是this的两倍,我想当我在谷歌搜索“java”关键字时让我失望。因此,至少有一个优势 - ThreadLocal更适合与任务并行库一起使用。

4 个答案:

答案 0 :(得分:2)

ThreadLocal<T>就像Dictionary<Thread, T>一样。字典的问题在于属于被杀死或死亡线程的实例永远存在 - 它们不会被垃圾收集,因为它们被字典引用。使用ThreadLocal将确保当线程死亡时,该线程引用的实例符合GC的条件。

另外,它是一个比手动处理Dictionary<Thread, T>更好的界面。它只是工作。

答案 1 :(得分:2)

  

我没有利用ThreadLocal而不是为线程创建对象的实例。

你是对的,当你控制正在创建的线程以及如何使用它们时,将整个线程包装在一个帮助器类中是非常方便的,并让它从那里获得“线程本地”数据

问题是,特别是在体制性大的项目中,你并不总是有这种控制。您可以启动一个线程,并调用一些代码,并且一个线程可以通过调用数百万行代码分散在3个内部团队和一个外部承包商团队拥有的10个项目之间。祝你好运,随处可见其中的一些参数。

线程局部存储允许这些人进行交互,而不需要他们对表示该线程上下文的对象有明确的引用。

我遇到的一个相关问题是将数据关联到某个线程该线程创建的每个子线程(因为我的大型项目创建了自己的线程,因此线程本地不再起作用) ,看到我有这个问题:Is there any programmable data that is automatically inherited by children Thread objects?

在一天结束时,它通常是懒惰的编程,但有时你会发现你需要它的情况。

答案 2 :(得分:0)

ThreadLocal比ThreadStatic属性方法有两个好处,你可以避免定义类字段,它内置了延迟加载功能。你的手动收集方法需要锁定机制,如果你看看ThreadLocal的源代码,你会看到它针对这个特定情况进行了优化。

答案 3 :(得分:0)

当T型对象new和gc频繁出现时,ThreadLocal可以获得好处。它的线程安全。