[C#]C#學習筆記-垃圾回收機制
C#學習筆記-垃圾回收機制
羅朝輝(http://www.rzrgm.cn/kesalin/)
《C#與.NET高級程序設計》讀書筆記
1,C#的垃圾回收機制
C#的垃圾回收機制不是基于引用計數的,而是基于對象是否可到達。該機制的運作過程是:CLR 會建立一個對象圖,代表堆上可達的每一個對象,如果在一次垃圾回收過程中,某個對象在該對象圖上沒有root(即沒有任何其他對象依賴于它),則對象是不可達對象,會被標記為垃圾,從而會被終結,從內存中清除。 微軟的回收算法使用對象代,用于終結對象的輔助線程和專門承載大對象的托管堆進行優化以提高垃圾回收機制的效率。
2,終結過程
Finalize() 的作用是保證.NET對象能在垃圾回收時清除非托管資源。如果創建了一個不使用非托管實體的類型,終結是沒有用的。事實上,盡可能在設計時避免提供Finalize()以提高效率,因為終結是需要花費時間的。當在托管堆上分配對象時,運行庫自動確定該對象是否提供一個自定義的Finalize()方。如果是這樣的話,該對象就被標記為可終結的,同時一個指向該對象的指針被保存至名為終結隊列的內部隊列中。終結隊列是一個由垃圾回收器維護的表,它指向每一個在從堆上刪除之前必須被終結的對象。
當垃圾回收器確定需要從內存中釋放一個對象時,它會檢查終結隊列中的每一項,并將對象從堆上復制到另一個稱作終結可達表的托管結構上。此時,下一個垃圾回收時將產生另一個線程,為每一個可達表中的對象調用Finalize()方法。因此,為了真正終結一個對象,至少要進行兩次垃圾回收。
總而言之,盡管對象的終結能夠保證對象可以清除非托管的資源,但它本質上仍然是非確定的,而且由于額外的幕后處理,速度會變得相當慢。為了盡可能快地釋放非托管資源,我們引入了 IDisposable 接口,該接口定義了一個名為 Dispose() 的方法,該方法假設當對象的用戶不再使用該對象時,會這個對象引用離開作用域之前手工地調用 Dispose()。這樣對象可以執行任何必要的非托管資源的清除,而不會再有對象放在終結隊列上導致的性能損失,也不必等到垃圾回收觸發類的終結邏輯。
Finalize()只適用于類類型,而 IDisposable 接口對結構和類類型均適用。注意,如果對象支持 IDisposable 接口,那么總是要對任何直接創建的對象調用 Dispose(),因為如果類設計者選擇實現該接口,說明該類需要手動執行清理工作。注意:基類庫中的許多類型實現了該接口,并提供了 Dispose() 方法的別名,如 System.IO.FileSteam類 Close()。我們可以不管別名,只調用 Dispose() 總是正確的。
3,可重用 using 關鍵字來簡化在 try/finally 塊中手動調用 Dispose() 方法的編寫。using 語法保證當使用支持 IDisposable接口的.NET類型的對象在退出using塊時,該對象會自動調用Dispose()方法。
4,可終結類型是重寫了System.Object.Finalize()虛方法(在析構函數中編寫清除代碼)以在回收垃圾時清除非托管資源的類。而可處置對象是實現了IDisposable接口的類或結構,對象用戶將在IDisposable接口被實行后調用它。我們可以將這兩種方式結合,如果對象用戶調用了Dispose(),則可以通過調用GC.SuppressFinalize()通知垃圾回收器跳過終結過程;如果對象用戶忘記調用Dispose(),對象最終也將被終結并有機會釋放內部資源。對象的內部非托管資源總會用其中一種方式被釋放掉。
浙公網安備 33010602011771號