GC管理 总结
面试经常会遇到GC管理的问题,每次问到的时候都会如实回答,没研究过,然后大家就知道结果是什么了。今天特别看了关于GC的教程,视频说的挺好的,我也做了如下几个笔记,如果哪里写的有问题,也请提出来一起探讨。
GC的主要功能:GC主要负责回收内存,对于非托管资源只能进行辅助性的回收。
GC处理的步骤:GC启动 Mark(标记),Compact(压缩),Update(更新)
1. 扫描并标记-找到垃圾对象
2. 压缩-回收垃圾对象
3. 更新指针
GC的特点:标记-压缩算法
1. 分配速度快,回收速度慢
2. 确保空闲内存区域连续,避免内存碎片
3. 对象地址不稳定(过一段时间垃圾回收器就会搬移一次,也因此C#不能输出对象的地址)
一. 资源管理与分类:托管资源与非托管资源
托管资源:托管堆内存
非托管资源:文件句柄,数据库链接,本地内存等
二. 内存的分配与管理
.net线式分配,间歇性压缩搬移对象内存(快,无碎片)
C++链式分配,对象地址稳定不变(慢,有碎片)
三. 内存的销毁
.net由系统在非确定时刻(启发式算法)收集(慢)
c++由程序员在确定时刻收集(即调用delete)(快)
分代式垃圾收集
一. CLR执行一个单独的线程来负责垃圾收集器,这时它会挂起当前所有线程
二. 分代式垃圾收集:区分对象代龄基于以下假设:
对象越新,其生存周期越短
对象越老,其生存周期越长
三. 8/2原则
GC收集一部分对象的“性价比”要高于一个对象和收集所有对象的效率
四. 每个托管堆对象分配一个代龄
0代对象限额:256k(垃圾对象)
1代对象限额:2M
2代对象限额:10M
GC是先回收0代,然后在根据大小回收1,2代。
IDisposable接口定义:定义一种释放分配的资源的方法。
析构函数与构造函数比较
构造函数定义: 构造函数是和类同名,没有返回值。
析构函数定义: 在类名前加~,也没有返回值。
构造函数执行过程:构造函数上在对象创建时执行。
析构函数执行过程:析构函数是在程序结束时执行,一般时候析构函数里面写的都是一些资源回收之类的东西,不过C#的析构函数的调用机制和C++不同.并不能保证每次都会调用.所以最好不要利用C#的析构函数来回收资源。
析构器两大缺点(本质会编译成Finalize)
1. 拖大了对象的代龄(处理方法在Close回收方法中写入GC.SupperssFinalize(this),那么程序会认为没有写析构方法)
2. 回收资源不及时(写一个Close方法自动回收)
析构器编写是怕程序员忘记调用close方法了。
只要继承IDisposable ,这个类就是资源类,就要调用Dispose()
终结操作:Finalize方法
1. 非托管资源的清理: GC主要负责回收内存,对于非托管资源只能进行辅助性的回收。
2. C#析构器与Object.Finalize虚方法
3.如果判断一个类需要终结操作?该类或者其某个父类(Object除外)实现了析构器(重写了Finalize)
4. GC非确定性执行:终结操作的执行时间分析
5.垃圾收集器并不保证终结操作的顺序
避免两个对象的终结操作有顺序的依赖
6.长弱引用于短弱引用
利用弱引用缓存对象
Dispos设计模式
一. 终结操作(就是析构器)给对象带来的性能负担
1. 如果一个对象需要终结操作,GC会因此而提升其代龄,从而延迟收集对象。
2. 终结操作本身是非确定性的,是潜在资源泄漏
二. 确定性清理:Dispose设计模式
1. Idisposable.DisPose()接口方法
2. 析构器(Finalize方法)
3. 在Dispose方法中调用GC.SuppressFinalize(避免Finalize被GC调用 这个方法就是当作没写析构器)
三. using语句与Dispose模式
对技术有兴趣的朋友可以加入群:245507606 好好学习,天天向上.......