【问题标题】:Finalization Reachable Table最终确定可达表
【发布时间】:2010-11-12 03:10:02
【问题描述】:

如果我在类 Foo 中实现析构函数,则 Foo 的实例将在终结队列上密切跟踪。当 Foo 的实例被垃圾收集时,我知道 CLR 会看到终结队列中的条目,并通过将对象移出堆并进入终结可达表来对该对象进行特殊处理。那么......垃圾回收周期没有其他任何事情发生?

在下一个垃圾回收周期中是否总是会调用 finalize()?

为什么在将我的对象复制到 freachable 表后不立即调用 finalize? (这似乎是额外的不必要的复杂性)

【问题讨论】:

    标签: clr destructor finalize


    【解决方案1】:

    终结器队列是为了简化事情;没有它会更复杂。当 GC 运行时,不必执行托管代码 - 否则如果用户代码在中间运行,GC 所做的所有分析都可能无效。

    因此,当 GC 运行时,必须推迟终结,而不是立即执行。在单独的线程中运行它可以最大限度地减少 VM 需要独占访问所有线程的时间,并增加并发活动的可能性。

    【讨论】:

    • 明白。但是为什么垃圾收集器在完成循环后不直接关闭 Finalize() 线程呢?为什么要等待下一个周期?
    • 你认为它为什么不这样做?当一个对象是可终结的,但在其他方面无法访问时,它会被添加到 freachable 队列中。在那里,终结器线程将在垃圾收集完成后立即将其拾取。
    • Andrew Troelsen 说:“此时,会产生一个单独的线程,以便在下一次垃圾回收时为 freachable 表上的每个对象调用 Finalize() 方法。鉴于此,它至少需要两个垃圾回收来真正完成一个对象”(p191 - Pro C# with .NET 3.0)
    • 我面前没有这本书,但我认为它是错误的或被误解的。对象在 GC 完成后立即完成。但是,它们的内存只会在下一次 GC 时回收,因此需要两个 GC 周期才能真正释放可终结对象的内存。
    猜你喜欢
    • 1970-01-01
    • 2016-08-23
    • 2021-07-06
    • 2018-08-28
    • 2021-10-14
    • 1970-01-01
    • 2020-11-15
    • 2011-12-24
    • 1970-01-01
    相关资源
    最近更新 更多