ThreadLocal<T> 时内存泄漏用于循环图中 [英] Memory leak when ThreadLocal&lt;T&gt; is used in cyclic graph

查看:24
本文介绍了ThreadLocal<T> 时内存泄漏用于循环图中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚发现垃圾收集器关于 System.Threading.ThreadLocal 的这种奇怪的行为",我无法解释.在正常情况下,ThreadLocal 实例在超出范围时会被垃圾回收,即使它们没有被正确处理,除非它们是循环对象图的一部分.

I just came across this weird 'behavior' of the Garbage Collector concerning System.Threading.ThreadLocal<T> that I can't explain. In normal circumstances, ThreadLocal<T> instances will be garbage collected when they go out of scope, even if they aren't disposed properly, except in the situation where they are part of a cyclic object graph.

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

The following example demonstrates the problem:

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 不是一个好习惯,但即使没有调用 Dispose,最终清理资源(通过调用终结器)也是 CLR 的设计.

Although not calling Dispose is not good practice, but it's the CLR's design to clean up resources (by calling the finalizer) eventually, even if Dispose is not called.

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

Why does ThreadLocal behave differently in this regard and can cause memory leaks when not disposed properly in case of a cyclic graph? Is this by design? And if so, where is this documented? Or is this a bug in the CLR's GC?

(在 .NET 4.5 下测试).

(Tested under .NET 4.5).

推荐答案

Microsoft 的 David Kean 确认这实际上是一个错误.

Microsoft's David Kean confirmed that this actually is a bug.

这篇关于ThreadLocal<T> 时内存泄漏用于循环图中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆