垃圾收集和终结器:更精细的点 [英] Garbage Collection and Finalizers: Finer Points

查看:18
本文介绍了垃圾收集和终结器:更精细的点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在回答关于 SO 的另一个问题* 以及随后的评论讨论时,我遇到了一个我不清楚的问题.

In answering another question* on SO, and the subsequent comment discussion, I ran into a wall on a point that I'm not clear on.

在我误入歧途的任何地方纠正我......

Correct me on any point where I'm astray...

当垃圾收集器收集一个对象时,它会在单独的线程上调用该对象的终结器(除非终结器已被抑制,例如通过 Dispose() 方法).收集时,GC 会挂起除触发收集的线程之外的所有线程(后台收集除外).

When the Garbage Collector collects an object, it calls that object's finalizer, on a separate thread (unless the finalizer has been suppressed, e.g. through a Dispose() method). While collecting, the GC suspends all threads except the thread that triggered the collection (background collection aside).

不清楚的地方:

  1. 垃圾收集器在收集之前是否等待终结器对该对象执行?
  2. 如果没有,它是否会在终结器仍在执行时取消挂起线程?
  3. 如果它确实在等待,如果终结器遇到一个被挂起的线程持有的锁,会发生什么?终结器线程是否死锁?(在我的回答中,我认为这是一个糟糕的设计,但我可能会看到可能发生这种情况的案例)

* 原问题的链接:
.NET GC 从终结器访问同步对象

* Link to the original question:
.NET GC Accessing a synchronised object from a finalizer

推荐答案

垃圾收集器在收集之前是否等待终结器对该对象执行?

Does the Garbage Collector wait for the finalizer to execute on that object before collecting it?

你的问题有点含糊.

当 GC 遇到需要终结的死"对象时,它会放弃回收死对象存储的尝试.相反,它将对象放入我知道需要终结的对象"队列中,并将该对象视为活动对象,直到终结器线程完成.

When the GC encounters a "dead" object that needs finalization, it abandons its attempt to reclaim the dead object's storage. Instead, it puts the object on a queue of "objects that I know need finalization" and treats that object as alive until the finalizer thread is done with it.

所以,是的,在回收存储之前,GC 确实等待"直到执行终结器.但它不会同步地等待.听起来您在问GC 是否在此处同步调用终结器?"不,它会排队等待稍后完成的对象并继续运输.GC 希望快速完成释放垃圾和压缩内存的任务,以便适当的程序可以尽快恢复运行.它不会停止处理一些在清理之前需要注意的抱怨对象.它将该对象放在一个队列中并说安静,终结器线程将在稍后处理您."

So, yes, the GC does "wait" until the finalizer is executed before reclaiming the storage. But it does not wait synchronously. It sounds like you're asking "does the GC synchronously call the finalizer right there?" No, it queues up the object to be finalized later and keeps on truckin'. The GC wants to quickly get through the task of releasing garbage and compacting memory so that the program proper can resume running ASAP. It's not going to stop to deal with some whiny object that is demanding attention before it gets cleaned up. It puts that object on a queue and says "be quiet and the finalizer thread will deal with you later."

稍后 GC 将再次检查对象并说你还死了吗?你的终结器运行了吗?"如果答案是是",那么该对象将被回收.(请记住,终结器可能会将死对象变成活对象;尽量不要这样做.结果不会发生任何令人愉快的事情.)

Later on the GC will check the object again and say "are you still dead? And has your finalizer run?" If the answer is "yes" then the object gets reclaimed. (Remember, a finalizer might make a dead object back into a live one; try to never do that. Nothing pleasant happens as a result.)

它是否在终结器仍在执行时取消挂起线程?

Does it un-suspend threads while the finalizer is still executing?

我相信 GC 会解冻它冻结的线程,并向终结器线程发出嘿,你有工作要做"的信号.所以当终结器线程开始运行时,被 GC 冻结的线程又重新启动了.

I believe that the GC thaws out the threads that it froze, and signals the finalizer thread "hey, you've got work to do". So when the finalizer thread starts running, the threads that were frozen by the GC are starting up again.

可能必须有解冻线程,因为终结器可能需要将调用编组到用户线程以释放线程相关资源.当然,其中一些用户线程可能被阻塞或冻结;线程总是会被某些东西阻塞.

There might have to be unfrozen threads because the finalizer might require a call to be marshalled to a user thread in order to release a thread-affinitized resource. Of course some of those user threads might be blocked or frozen; threads can always be blocked by something.

如果终结器遇到被挂起线程之一持有的锁会发生什么?终结器线程是否死锁?

what happens if the finalizer runs into a lock being held by one of the suspended threads? Does the finalizer thread deadlock?

你打赌.终结器线程没有什么神奇的东西可以防止它死锁.如果用户线程正在等待终结器线程取出的锁,而终结器线程正在等待用户线程取出的锁,那么您就遇到了死锁.

You betcha. There's nothing magic about the finalizer thread that prevents it from deadlocking. If a user thread is waiting on a lock taken out by the finalizer thread, and the finalizer thread is waiting on a lock taken out by the user thread, then you've got a deadlock.

终结器线程死锁的例子比比皆是.这是一篇关于此类场景的好文章,其中包含许多其他场景的链接:

Examples of finalizer thread deadlocks abound. Here's a good article on one such scenario, with a bunch of links to other scenarios:

http://blogs.microsoft.co.il/blogs/sasha/archive/2010/06/30/sta-objects-and-the-finalizer-thread-tale-of-a-deadlock.aspx

正如文章所述:终结器是一种极其复杂且危险的清理机制,您应该尽可能避免使用它们.终结器很容易出错,但很难做到正确.

As the article states: finalizers are an extremely complex and dangerous cleanup mechanism and you should avoid them if you possibly can. It is incredibly easy to get a finalizer wrong and very hard to get it right.

这篇关于垃圾收集和终结器:更精细的点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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