垃圾收集器在收集之前是否等待终结器在该对象上执行?
你的问题有点模棱两可。
当 GC 遇到需要终结的“死”对象时,它会放弃回收死对象存储的尝试。相反,它将对象放在“我知道需要终结的对象”队列中,并将该对象视为活动对象,直到终结器线程完成它为止。
所以,是的,在回收存储之前,GC 确实“等待”直到执行终结器。但它不会同步等待。听起来您在问“GC 是否在此处同步调用终结器?” 不,它会排队等待稍后完成的对象并继续运输。GC 希望快速完成释放垃圾和压缩内存的任务,以便适当的程序可以尽快恢复运行。它不会停止处理一些在清理之前需要注意的抱怨对象。它将该对象放在一个队列中并说“安静,终结器线程将在稍后处理您。”
稍后 GC 将再次检查对象并说“你还死了吗?你的终结器运行了吗?” 如果答案是“是”,那么该对象将被回收。(请记住,终结器可能会将死对象变成活对象;尽量不要这样做。结果不会发生任何令人愉快的事情。)
它是否在终结器仍在执行时取消挂起线程?
我相信 GC 解冻了它冻结的线程,并向终结器线程发出信号“嘿,你有工作要做”。因此,当终结器线程开始运行时,被 GC 冻结的线程将再次启动。
可能必须有解冻线程,因为终结器可能需要将调用编组到用户线程以释放线程相关资源。当然,其中一些用户线程可能会被阻塞或冻结;线程总是可以被某些东西阻塞。
如果终结器遇到被挂起线程之一持有的锁会发生什么?终结器线程是否死锁?
完全正确。终结器线程没有什么神奇的东西可以防止它死锁。如果用户线程正在等待终结器线程取出的锁,而终结器线程正在等待用户线程取出的锁,那么您就遇到了死锁。
终结器线程死锁的例子比比皆是。这是一篇关于这样一个场景的好文章,有一堆指向其他场景的链接:
http://blogs.microsoft.co.il/blogs/sasha/archive/2010/06/30/sta-objects-and-the-finalizer-thread-tale-of-a-deadlock.aspx
正如文章所述:终结器是一种极其复杂且危险的清理机制,如果可能,您应该避免使用它们。将终结器弄错非常容易,而要让它正确则非常困难。