gpt4 book ai didi

.net - ThreadLocal<> 和内存泄漏

转载 作者:行者123 更新时间:2023-12-04 08:50:18 28 4
gpt4 key购买 nike

.Net 4. ThreadLocal<> 实现 IDisposable。但似乎调用 Dispose() 实际上并没有释放对所持有的线程本地对象的引用。

这段代码重现了这个问题:

using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;

namespace ConsoleApplication2
{
class Program
{
class ThreadLocalData
{
// Allocate object in LOH
public int[] data = new int[10 * 1024 * 1024];
};

static void Main(string[] args)
{
// Stores references to all thread local object that have been created
var threadLocalInstances = new List<ThreadLocalData>();
ThreadLocal<ThreadLocalData> threadLocal = new ThreadLocal<ThreadLocalData>(() =>
{
var ret = new ThreadLocalData();
lock (threadLocalInstances)
threadLocalInstances.Add(ret);
return ret;
});
// Do some multithreaded stuff
int sum = Enumerable.Range(0, 100).AsParallel().Select(
i => threadLocal.Value.data.Sum() + i).Sum();
Console.WriteLine("Sum: {0}", sum);
Console.WriteLine("Thread local instances: {0}", threadLocalInstances.Count);

// Do our best to release ThreadLocal<> object
threadLocal.Dispose();
threadLocal = null;

Console.Write("Press R to release memory blocks manually or another key to proceed: ");
if (char.ToUpper(Console.ReadKey().KeyChar) == 'R')
{
foreach (var i in threadLocalInstances)
i.data = null;
}
// Make sure we don't keep the references to LOH objects
threadLocalInstances = null;
Console.WriteLine();

// Collect the garbage
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

Console.WriteLine("Garbage collected. Open Task Manager to see memory consumption.");
Console.Write("Press any key to exit.");
Console.ReadKey();
}
}
}

线程本地数据存储对大对象的引用。如果引用没有被手动清零,GC 不会收集这些大对象。我使用任务管理器来观察内存消耗。我还运行内存分析器。我在垃圾收集后做了一个快照。探查器显示泄漏的对象由 GCHandle 根并在此处分配:
mscorlib!System.Threading.ThreadLocal<T>.GenericHolder<U,V,W>.get_Boxed()
mscorlib!System.Threading.ThreadLocal<T>.get_Value()
ConsoleApplication2!ConsoleApplication2.Program.<>c__DisplayClass3.<Main>b__2( int ) Program.cs

这似乎是 ThreadLocal<> 设计中的一个缺陷。存储所有分配的对象以供进一步清理的技巧是丑陋的。关于如何解决这个问题的任何想法?

最佳答案

内存可能已被垃圾回收,但 CLR 进程还没有释放它。它倾向于保留已分配的内存,以防以后需要它,因此不必进行昂贵的内存分配。

关于.net - ThreadLocal<> 和内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7567088/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com