C# 垃圾回收机制深度解析与实践
1. 资源释放的常见问题
在编程过程中,有些对象需要特殊的代码来释放资源。以下是一些常见的例子:
- 打开文件后忘记关闭。
- 注册事件后忘记注销。
- 处理非托管对象、使用锁定机制或操作系统句柄时,忘记正确释放资源。
在 C# 中,程序员可以通过显式处理对象来释放资源,或者让公共语言运行时(CLR)通过垃圾回收(GC)机制自动释放资源。
2. 垃圾回收的工作原理
垃圾回收器采用分代回收策略,对短生命周期对象的回收频率高于长生命周期对象。这里有三代:0 代、1 代和 2 代。短生命周期对象存储在 0 代,长生命周期对象会被提升到更高的代(1 代或 2 代)。垃圾回收器在低代的工作频率高于高代。
当创建一个对象时,它最初位于 0 代。当 0 代满时,垃圾回收器被调用。在第一次垃圾回收中存活下来的对象会被提升到 1 代,在 1 代垃圾回收中存活的对象会移动到 2 代。
垃圾回收工作分为三个不同的阶段,一般在三种不同的情况下会调用垃圾回收器:
|阶段|描述|
| ---- | ---- |
|标记阶段|标记或识别存活对象。|
|重定位阶段|更新将在第 3 阶段进行压缩的对象的引用。|
|压缩阶段|从死亡/未引用的对象中回收内存,并对存活对象执行压缩操作,将存活对象移动到段的较旧端。|
垃圾回收器从根对象引用开始工作,跟踪对象图以识别可访问的对象。处理完成后,未标记的对象将被垃圾回收。没有析构函数的未标记对象的内存会立即被垃圾回收器回收。有析构函数的对象会被放入终结队列。