2009-07-08 64 views
25

我理解並欣賞System.WeakReference類在.NET框架中的實用性,但對實現細節很好奇。.NET中的WeakReference實現

WeakReference如何在.NET中實現? MSDN詳細討論了WeakReference的用法,但我沒有看到關於如何在底層工作的細節。

在收集目標時,CLR如何跟蹤引用並知道內部句柄爲空,而不阻止GC?它是否需要在CLR中進行特殊處理?

我主要關心的是是否存在使用WeakReferences的性能影響(特別是如果使用WeakReferences的話),這與使用標準對象引用的性能有什麼不同。

+5

我已經做了相當多的研究,並詳細地發表了我的發現:http://reedcopsey.com/?p=50 – 2009-07-09 00:07:55

回答

19

WeakReference類將其對象引用移交給GC並獲取句柄。無論何時您獲取參考或檢查參考是否存在,該句柄都用於向GC詢問參考。

這意味着GC會保存所有弱引用的列表,這些引用在收集對象時必須更新。這也意味着每次使用弱引用時都會有一些開銷。因此,每個弱引用對垃圾收集器來說意味着更多的工作,但是另一方面,每個常規引用​​也是如此,即使它的數量較少也是如此。您當然應該小心使用大量弱引用,但是如果您需要使內存管理與對象一起運行良好,那麼應該超出其導致的小額開銷。

13

您提到MSDN;你有沒有看過這篇文章?

http://msdn.microsoft.com/en-us/magazine/bb985011.aspx

由同一作者(傑弗裏裏希特)另外,請查閱第19章中的 「應用的Microsoft .NET Framework編程」。本章是關於垃圾收集的,並且有一個關於WeakReference內部的章節。

一般來說,如果你在WeakReferences中訪問很多Targets,那麼性能就會受到影響,只是因爲WeakRef在返回目標之前做了一些工作(主要是爲了線程安全)。這顯然不如直接使用對象引用便宜。另一方面,當存儲對大對象的引用時,你會獲得一些性能,因爲當出現內存問題時,垃圾收集器有更多的選項。

我從來沒有試圖量化這種交易,或知道這裏的任何參考。顯然,這取決於應用程序而有所不同。

+2

+1,並感謝參考資料。只是FYI,我已經做了更多的研究,並且在WeakReference中線程安全的開銷少得驚人 - 大多數情況下,必須讓GCHandle將對象作爲兩次解除引用的對象,再加上一些空的檢查。 – 2009-07-09 00:07:13

+0

我以爲我記得在幾年前看到這種情況,但我真的應該在回答它之前確認它。謝謝你注意到裏德。 – ars 2009-07-09 00:41:01