【问题标题】:C# ThreadStaticAttribute marked fields are automatically released when thread dies?C# ThreadStaticAttribute 标记的字段在线程死亡时自动释放?
【发布时间】:2011-01-05 16:51:46
【问题描述】:

我发现了“ThreadStaticAttribute”,对此我有很多疑问: 我以前所有的线程相关的静态信息,都被实现为一个静态字典,其中 TKey 是 Thread,当我想访问它时,我使用了 Thread.CurrentThread 并且有效。但这需要维护,因为如果一个线程死了,我必须从字典中删除相应的条目。而且我还需要考虑线程安全以及许多其他问题。

通过使用 ThreadStaticAttribute,所有这些问题似乎都解决了,但我需要确定这一点。我的问题是:我是否需要在线程死亡之前以某种方式删除由“ThreadStaticAttribute”标记的字段持有的实例?该字段的信息在哪里保存?它在Thread对象的实例中,或者类似的东西,所以当它不再使用时,垃圾收集器会自动丢弃它?有性能惩罚吗?有哪些?是否比我之前使用的 Keyed 集合更快?

请,我需要澄清一下“ThreadStaticAttribute”的工作原理。

谢谢。

【问题讨论】:

    标签: c# multithreading static


    【解决方案1】:

    不,您不需要删除标记为ThreadStatic 的字段中的帮助值实例。当线程和对象都不再被根对象访问时,垃圾收集器将自动拾取它们。

    这里唯一的例外是如果该值实现了IDisposable,并且您想主动处置它。一般来说,这是一个很难解决的问题,原因有很多。没有实现 IDisposable 并位于 ThreadStatic 字段中的值要简单得多。

    至于这个字段实际存储在哪里,这有点无关紧要。您需要担心的是它的行为与 .Net 中的任何其他对象一样。唯一的两个行为差异是

    1. 该字段将引用每个访问线程的不同值。
    2. 该字段的初始化程序只会运行一次(实际上,有任何初始化程序是个坏主意)。

    【讨论】:

      【解决方案2】:

      将静态成员变量标记为 [ThreadStatic] 告诉编译器将其分配到线程的内存区域(例如,分配线程堆栈的位置)而不是全局内存区域。因此,每个线程都有自己的副本(保证初始化为该类型的默认值,例如 null、0、false 等;不要使用内联初始化程序,因为它们只会为一个线程初始化它)。

      所以,当线程消失时,它的内存区域也会消失,释放引用。当然,如果它需要更直接的处理(打开文件流等)而不是等待后台垃圾收集,您可能需要确保在线程退出之前执行此操作。

      可用的 [ThreadStatic] 空间量可能存在限制,但对于正常使用来说应该足够了。它应该比访问键控集合要快一些(并且更容易线程安全),而且我认为它与访问普通静态变量相当。

      更正:我听说访问 ThreadStatic 变量比访问普通静态变量要慢一些。我不确定它是否真的比访问键控集合更快,但它确实避免了孤儿问题(这是你的问题)和需要锁定线程安全,这会使键控集合方法复杂化。

      【讨论】:

      • 编译器确实对ThreadStatic 属性没有任何作用。它完全由 CLR 处理
      • 好的,但是从隐喻意义上而不是严格的字面意义上来理解“编译器”,您就知道如何使用该属性了。
      猜你喜欢
      • 2018-02-22
      • 2019-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-26
      相关资源
      最近更新 更多