GC.Collect() 和完成 [英] GC.Collect() and Finalize

查看:31
本文介绍了GC.Collect() 和完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,众所周知,当 GC 将对象识别为垃圾时,它会隐式调用对象的 Finalize 方法.但是如果我执行 GC.Collect() 会发生什么?终结器是否仍在执行?可能是个愚蠢的问题,但有人问我这个问题,我回答是",然后我想:这完全正确吗?"

Ok, it's known that GC implicitly calls Finalize methods on objects when it identifies that object as garbage. But what happens if I do a GC.Collect()? Are the finalizers still executed? A stupid question maybe, but someone asked me this and I answered a "Yes" and then I thought: "Was that fully correct?"

推荐答案

好的,众所周知,当 GC 将对象识别为垃圾时,它会隐式调用对象的 Finalize 方法.

Ok, it's known that GC implicitly calls Finalize methods on objects when it identifies that object as garbage.

不不不.这不是已知,因为要成为knowledge,一个陈述必须是true.该陈述是错误.垃圾收集器在跟踪时不会运行终结器,无论它是自行运行还是您调用 Collect.终结器线程在跟踪收集器找到垃圾后运行终结器,并且对于 Collect 的调用异步发生.(如果它发生了,它可能不会发生,正如另一个答案指出的那样.)也就是说,你不能依赖在控制从 Collect 返回之前执行的终结器线程.

No no no. That is not known because in order to be knowledge a statement must be true. That statement is false. The garbage collector does not run finalizers as it traces, whether it runs itself or whether you call Collect. The finalizer thread runs finalizers after the tracing collector has found the garbage and that happens asynchronously with respect to a call to Collect. (If it happens at all, which it might not, as another answer points out.) That is, you cannot rely on the finalizer thread executing before control returns from Collect.

以下是其工作原理的简化草图:

Here's an oversimplified sketch of how it works:

  • 当收集发生时,垃圾收集器跟踪线程会跟踪根——已知的活动对象,以及它们引用的每个对象,等等——以确定死对象.
  • 具有挂起终结器的死"对象被移动到终结器队列中.终结器队列是根.因此,那些死"的物体实际上还活着.
  • 终结器线程(通常是与 GC 跟踪线程不同的线程)最终运行并清空终结器队列.然后这些对象就真正死了,并被收集到跟踪线程上的 next 集合中.(当然,由于它们刚刚在第一个系列中幸存下来,它们可能处于更高的一代.)
  • When a collection happens the garbage collector tracing thread traces the roots -- the objects known to be alive, and every object they refer to, and so on -- to determine the dead objects.
  • "Dead" objects that have pending finalizers are moved onto the finalizer queue. The finalizer queue is a root. Therefore those "dead" objects are actually still alive.
  • The finalizer thread, which is typically a different thread than the GC tracing thread, eventually runs and empties out the finalizer queue. Those objects then become truly dead, and are collected in the next collection on the tracing thread. (Of course, since they just survived the first collection, they might be in a higher generation.)

正如我所说,这过于简单了;终结器队列如何工作的确切细节比这要复杂一些.但它已经足够传达这个想法了.这里的实际结果是 您不能假设调用 Collect 也会运行终结器,因为它不会.让我再重复一遍:垃圾收集器的跟踪部分运行终结器Collect只运行收集机制.

As I said, that's oversimplified; the exact details of how the finalizer queue works are a bit more complicated than that. But it gets enough of the idea across. The practical upshot here is that you cannot assume that calling Collect also runs finalizers, because it doesn't. Let me repeat that one more time: the tracing portion of the garbage collector does not run finalizers, and Collect only runs the tracing part of the collection mechanism.

如果您想保证所有终结器都已运行,请在调用 Collect 之后调用恰当命名的 WaitForPendingFinalizers.这将暂停当前线程,直到终结器线程开始清空队列.如果你想确保这些最终对象的内存被回收,那么你将不得不调用 Collect 次.

Call the aptly named WaitForPendingFinalizers after calling Collect if you want to guarantee that all finalizers have run. That will pause the current thread until the finalizer thread gets around to emptying the queue. And if you want to ensure that those finalized objects have their memory reclaimed then you're going to have to call Collect a second time.

当然,不言而喻,您应该只出于调试和测试目的而这样做.千万不要在没有真正真正充分理由的情况下在生产代码中做这种废话.

And of course, it goes without saying that you should only be doing this for debugging and testing purposes. Never do this nonsense in production code without a really, really good reason.

这篇关于GC.Collect() 和完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆