c# - 在循环图中使用 ThreadLocal<T> 时发生内存泄漏

标签 c# .net memory-leaks garbage-collection .net-4.5

我刚刚遇到垃圾收集器关于 System.Threading.ThreadLocal<T> 的奇怪“行为”我无法解释。一般情况下,ThreadLocal<T>实例超出范围时将被垃圾收集,即使它们没有被正确处理,除非它们是循环对象图的一部分。

下面的例子演示了这个问题:

public class Program
{
    public class B { public A A; }
    public class A { public ThreadLocal<B> LocalB; }

    private static List<WeakReference> references = new List<WeakReference>();

    static void Main(string[] args) {
        for (var i = 0; i < 1000; i++)
            CreateGraph();

        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        GC.WaitForPendingFinalizers();

        // Expecting to print 0, but it prints 1000
        Console.WriteLine(references.Count(c => c.IsAlive));
    }

    static void CreateGraph() {
        var a = new A { LocalB = new ThreadLocal<B>() };
        a.LocalB.Value = new B { A = a };
        references.Add(new WeakReference(a));

        // If either one of the following lines is uncommented, the cyclic
        // graph is broken, and the programs output will become 0.
        // a.LocalB = null;
        // a.LocalB.Value = null;
        // a.LocalB.Value.A = null;
        // a.LocalB.Dispose();
    }
}

虽然没有调用 Dispose这不是好的做法,但最终清理资源(通过调用终结器)是 CLR 的设计,即使 Dispose 也是如此。不被调用。

为什么 ThreadLocal在这方面表现不同,并且在循环图的情况下如果处理不当会导致内存泄漏?这是设计使然吗?如果是这样,这在哪里记录?或者这是 CLR 的 GC 中的错误?

(在 .NET 4.5 下测试)。

最佳答案

微软的David Kean confirmed这实际上是一个错误。

关于c# - 在循环图中使用 ThreadLocal<T> 时发生内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33172615/

相关文章:

c# - 枚举类型数组的命令行解析器

c# - 强制 C# 应用程序在 64 位服务器上以 32 位模式运行

c# - 如何使用 BouncyCaSTLe Blowfish 实现解密数据?

.net - 用户“NT AUTHORITY\ANONYMOUS LOGON”登录失败

C# 问题修剪字符串中的换行符

.net - 如何在没有 .NET SDK 或 Visual Studio 的情况下安装 .net dll?

c# - 使用 mongoDB C# 驱动程序,如何发出 runCommand?

java - 多线程 Java Web 服务器中的内存泄漏

Java:泄漏原因未知(非常简单的示例)

memory-leaks - Sitecore实例崩溃-分析内存转储的最佳工具是什么?