.NET的资源管理—11.理解并善用.NET的资源管理机制

.NET程序运行在托管环境中,开发者必须从.NET CLR的绝对来思考,才可以充分发挥这套环境的优势。必须理解垃圾回收机制和对象生存期。

.NET提供GC来控制托管内存,非托管的资源需要开发者来控制。例如数据库连接、GDI+对象、COM对象以及其他一些系统对象。

垃圾回收器每次运行是都会压缩托管堆,以便把其中的活动对象安排在一起,使得空闲内存能够形成一块连续的区域。

有两种机制可以控制非托管资源的生存期,一种是finalizer(终止器),另一种是IDisposable接口。finalizer是一种防护机制,可以确保对象总是能够把非托管资源释放掉,但这种机制有很多缺陷,所以应该考虑通过IDisposable接口来及时将资源返回给系统。

finalizer,当垃圾回收器把对象判定为垃圾之后,他会择机调用该对象的finalizer,但开发者并不知道具体的时机,你只能确认在大多数情况下,当对象变得不可达之后,其finalizer就会得到调用,但执行的并不及时。依赖finalizer会降低程序的性能,因为垃圾回收器需要执行更多的工作才能终止这些对象。如果GC发现某个对象已成为垃圾,但该对象还要执行finalizer,要等finalizer执行完后才能将其移走。调用finallizer的那个线程并不是GC所在线程。GC在每一个周期里会把包好finalizer但是尚未执行的那些对象放在队列中,以便安排其finalizer的运行工作,而不含finalizer的对象则会直接从内存清掉。等到下一周期,GC会把已经执行了finalizer的对象删掉,因此局部finalizer的对象还需在内存中多待一段时间才能被GC清理掉。

为了优化垃圾回收工作,.NET的垃圾回收器定义了世代(generation)这个概念,以便尽快确定那些最有可能变成垃圾的对象。上一次收集完垃圾之后才创建出来的对象叫做第0代对象,如果其中某些对象在这次清扫之后还留在内存,那就变为第2代对象,若经过两次或更多次的清理之后它还留在内存中,则变为第二代对象。把对象分成不同的世代,可以将生存期较短的对象与全程伴随的对象区隔开。

GC每次循环,都会判断第0代对象是否垃圾,但每执行10次循环,才会把第1代对象连同第0代对象检测一遍,而第2代对象则是每100次循环才检测一遍。重新思考一下finalizer就会发现,与不带finalizer的对象相比,这种对象要在内存中多待9个周期,如果还没有得以终结则进入第2代,再等100个周期,才能由GC来收集它。

尽管花了很多时间来解释finalizer的缺点,但有些场合还是要释放资源,这可以用IDisposable接口及其标准的dispose模式来解决。

下一节将讲一些具体的技巧,帮你再托管环境下创建更为高效的程序。

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值