我一直在阅读新的并发集合,特别是ConcurrentBag引起了我的注意。由于ConcurrentBag内部在每个单独的线程中持有一个本地集以使用它来跟踪这些项,这意味着当线程本身超出范围时,它仍将由ConcurrentBag在内存中引用。这又意味着线程声明的内存以及本地资源? (请原谅我不知道.NET线程对象的确切内部工作原理)ConcurrentBag中可能的内存泄漏?
我可以假设一个用例,其中有1个全局ConcurrentBack用于多线程Web服务,其中有很多客户端添加任务。这些任务由线程池上的线程添加。现在线程池是管理线程的一种非常有效的方式,但它可以根据工作量删除和创建线程。因此,这种网络服务有时会遇到麻烦,因为底层包仍然引用许多应该被销毁的线程。
我创建了一个快速的应用程序来测试此行为:
static ConcurrentBag<int> bag = new ConcurrentBag<int>();
static void FillBag() { for (int i = 0; i < 100; i++) { bag.Add(i); } }
static void PrintState() { Console.WriteLine("Bag size is: {0}", bag.Count); }
static void Main(string[] args)
{
var remote = new Thread(x =>
{
FillBag();
PrintState();
});
// empty bag
PrintState();
// first 100 items are added on main thread
FillBag();
PrintState();
// second 100 items are added on remote thread
remote.Start();
remote.Join();
// since the remote thread is gone out of scope, what happened to its local storage which is part of the bag?
PrintState();
// now force a cleanup
WeakReference weakRemoteReference = new WeakReference(remote);
remote = null;
GC.Collect();
GC.WaitForPendingFinalizers();
// Now check if the thread still exists
if (weakRemoteReference.IsAlive)
Console.WriteLine("Remote thread still exists");
PrintState();
Console.ReadLine();
和输出印证了我的故事:
Bag size is: 0
Bag size is: 100
Bag size is: 200
Bag size is: 200
Remote thread still exists
Bag size is: 200
这种行为是可以预料的,我是不是犯了一个错误在我的测试或者这可以被认为是一个设计缺陷?
请注意,我命名远程线程已超出范围,当然它仍然在范围内,应该说:“由于远程线程已完成” – Polity 2011-03-18 14:11:12