为什么带有终结器的类需要多个垃圾回收周期?

时间:2012-01-27 07:21:26

标签: c# garbage-collection

This文章说

  

如果一个对象有一个终结器,那么当它没有被立即删除时   垃圾收集器决定它不再“活”。相反,它变成了   一种特殊的root,直到.NET调用终结器方法。   这意味着这些对象通常需要多个垃圾   要从内存中删除的集合,因为它们将在第一个中存活   他们被发现未被使用的时间。

我的问题是,当GC发现无法再引用对象并立即收集对象时,为什么不调用终结器?为什么它需要的不仅仅是垃圾收集?

3 个答案:

答案 0 :(得分:5)

要考虑两点:

  • 终结器可能需要一些时间才能完成。例如,它可能最终关闭资源或类似的东西。你不希望它成为垃圾收集时间的一部分,这可能阻止线程做工作(当他们只想获得一些内存时)。通过单独运行完成,GC本身可以非常快速地完成,并且最终确定工作可以与其他工作同时完成。

  • 终结者可以通过让对象再次可见来复活对象 - 但是检测到(我怀疑)还需要另外扫描内存......所以为什么不等到下一次它会发生?

答案 1 :(得分:2)

因为(取决于所选的GC模式)执行GC it has to pause key parts of the runtime时。因此,您希望尽可能快。这会产生两个问题:

  1. 它不知道终结器将运行多长时间(虽然它有一个硬限制),并且不想延迟恢复运行时
  2. 运行时需要运行才能使终结器可靠地工作(即使使用了GC线程,您编写的代码也可以考虑其他线程)
  3. 要解决这两个问题,那些具有待处理终结器的问题将排队,然后在 GC完成后(运行时工作时)执行

    作为旁注,最好将终结器与IDisposable结合起来并让Dispose()取消最终确定;这样,它不需要在以后完成,并且可以一步清理。

答案 2 :(得分:0)

当.net垃圾收集器运行时,对象分为三类:可从“普通”有根引用访问的对象,任何有根引用无法访问的对象,以及对象任何“正常”的有根引用都无法访问它们,但要么在它们被放弃时请求接收通知,或者可以从已经这样做的其他对象接收。垃圾收集器在第三类中创建对象列表;该列表存储为有根引用,使其中的所有对象“生效”。但是,系统会遍历该列表中的项目,取消其“通知”请求,运行Finalize()方法,并将其从列表中删除。如果在完成所有操作之后没有对该对象的引用存在,那么该对象将在下一个GC循环中被声明为“死”。