我一直在閱讀新的併發集合,特別是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