首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 內存管理深度解析(八):GC 根引用、標記壓縮與終結器隊列

     編輯:關於C語言

GC 根引用類型

標記-壓縮算法流程

  1. 標記:從根集合出發,遞歸遍歷所有可達對象,標記為「存活」。
  2. 壓縮:將存活對象向堆起始端移動,消除空洞,更新所有引用指針。
  3. 分配:新對象在壓縮後的空閒空間連續分配(指針碰撞),極快。

終結器機制詳細流程


class Obj { ~Obj() { /* 清理 */ } }

// 1. 創建 Obj 實例 → 進入「終結器隊列」
// 2. GC 標記階段發現 Obj 不可達,但有終結器
// 3. Obj 從終結器隊列移除,放入「F-reachable 隊列」
// 4. 專用 Finalizer 線程執行 Obj.Finalize()
// 5. 執行完成 → Obj 變為普通不可達對象
// 6. 下次 GC 循環真正回收內存

終結器代價

  • 對象至少經歷兩次 GC 才能回收(第一次進 F-reachable,第二次真正回收)。
  • Finalizer 線程單線程順序執行,阻塞會延遲所有終結器。
  • 終結器中拋出異常會終止進程(.NET 2.0+)。

替代方案:IDisposable + using

  • 應用層主動釋放,對象無需進入終結器隊列,單次 GC 即可回收。
  • 性能提升顯著,語義清晰。

代碼演示:終結器 vs IDisposable


// 終結器版
class WithFinalizer { ~WithFinalizer() { Console.WriteLine("Finalized"); } }

// IDisposable 版
class WithDispose : IDisposable
{
    public void Dispose() { Console.WriteLine("Disposed"); GC.SuppressFinalize(this); }
    ~WithDispose() { Dispose(); } // 保底
}

// 測試
using (var d = new WithDispose()) { } // 立即輸出 Disposed,無終結器開銷
var f = new WithFinalizer(); f = null; GC.Collect(); GC.WaitForPendingFinalizers(); // 輸出 Finalized,延遲兩次 GC
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
根類型示例
靜態字段static List _cache
線程棧變量方法局部變量、參數
CPU 寄存器JIT 產生的臨時引用
GC 句柄GCHandle.Alloc(obj)
終結器隊列對象有 ~Finalize() 的對象