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

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

问题描述

在回答记者有关SO另一个问题,以及随后的评论的讨论中,我遇到了对我不是明确点墙壁上。



在纠正我,在那里我误入歧途...



的任何一点

在垃圾收集器收集的对象,它会调用该对象的终结,在一个单独的线程(除非终结一直被压制,例如通过的Dispose()方法)。虽然收集,GC的暂停只是触发采集(采集背景除外)的线程的所有线程



什么是不明确的:




  1. 是否垃圾收集器收集么?

  2. 如果不是之前等待终结该对象上执行,不是取消暂停线程而终结仍在执行?

  3. 如果它不等待,如果终结跑进正在举行由挂起线程上的锁,会发生什么?是否终结线程死锁? (在我的答案,我认为这是糟糕的设计,但我可能看到的情况下会发生这种情况)



TIA,

詹姆斯



链接到原来的问题:

。NET的GC终结访问同步对象。


解决方案

请问垃圾收集器等待终结收集呢?


之前,该对象上执行< /块引用>

您的问题有点含糊。



当GC遇到死对象需要初始化,它放弃其尝试回收死对象的存储空间。相反,它使物体上的我知道需要终结的对象,直到终结器线程是用它做对象作为活着的对待队列。



所以,是的,确实GC直到终结被回收存储之前执行的等待。不过,这并不等待的同步的。这听起来像你问请问GC同步调用终结在那里?不,排队稍后完成的目标,并保持在道路行驶。在GC希望通过释放垃圾和压实内存,使程序正确就可以恢复运行尽快的任务迅速得到。它不会停下来对付它被清理之前,是需要关注的一些抱怨的对象。它把该对象的队列,并说:安静,后来终结器线程会对付你。



后来就GC将再次检查对象,并说:你还是死了?而且有你的终结跑?如果答案是是,那么对象被回收。 (请记住,一个终结可能使一个死的对象回到一个人住一间;尽量不会做,没有什么令人愉快的发生结果。)




是否同时终结仍在执行它取消暂停线程?




我相信GC解冻出它冻结线程和信号终结器线程哎,你有工作要做。所以当终结器线程开始运行,即是由气相冻结的线程重新启动。



有可能必须解冻线程因为终结可能需要一个呼叫为了释放一个线程affinitized资源将被编组为一个用户线程。当然,其中一些用户线程的可能的被堵塞或冻结的;线程总是可以通过一些被封锁。




如果终结跑进正在举行由挂起线程上的锁,会发生什么?是否终结线程死锁?




您betcha当。没有什么神奇的关于终结器线程,防止它死锁。如果用户线程正在等待被终结器线程取出的锁,并终结器线程正在等待由用户线程取出一把锁,那么你已经有了一个僵局。


$ B终结器线程死锁$ b

例子比比皆是。这里有一个这样的方案中的好文章,有一堆链接到其他场景:



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



由于文章说:终结是一个非常复杂和危险的清理机制,你应该避免他们,如果你所能。这是令人难以置信的容易得到终结错误的,很难得到它的权利。


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...

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).

What isn't clear:

  1. Does the Garbage Collector wait for the finalizer to execute on that object before collecting it?
  2. If not, does it un-suspend threads while the finalizer is still executing?
  3. If it does wait, what happens if the finalizer runs into a lock being held by one of the suspended threads? Does the finalizer thread deadlock? (In my answer, I argue that this is bad design, but I could possibly see cases where this could happen)

TIA,
James

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?

Your question is a bit ambiguous.

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.

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."

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?

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天全站免登陆