GC行为和CLR线程劫持

时间:2011-12-06 17:38:44

标签: c# garbage-collection clr

我正在阅读本书CLR via C#中关于GC的内容,特别是关于CLR何时想要开始收集的内容。我知道它必须在收集发生之前挂起线程,但它提到它必须在线程指令指针到达安全点时执行此操作。在它不在安全点的情况下,它会尝试快速找到一个,并且它通过hijacking线程(在线程堆栈中插入一个特殊的函数指针)来实现。这一切都很好,花花公子,但我认为默认情况下托管线程是安全的吗?

我最初认为它可能是指非托管线程,但CLR允许非托管线程继续执行,因为任何正在使用的对象都应该被固定。

那么,托管线程中的safe point是什么,以及GC如何确定它是什么?

编辑:

我认为我不够具体。根据{{​​3}},即使调用Thread.Suspend,在到达safe point之前,线程实际上也不会被暂停。它继续进一步说明safe point是线程执行中可以执行垃圾收集的点。

我想我的问题不清楚。我意识到一个线程只能在安全点暂停,并且它们必须暂停用于GC,但我似乎无法找到一个明确的答案,关于什么是安全点。是什么决定了代码中的安全点?

1 个答案:

答案 0 :(得分:14)

'安全点'是我们的所在地:

  1. 不在陷阱中。
  2. 不在最后
  3. 里面
  4. 不在锁内
  5. 不在p / invoke'd调用内(在托管代码中)。未在CLR中运行非托管代码。
  6. 内存树可以走路。
  7. 第5点有点令人困惑,但有时候内存树将无法行走。例如,在优化之后,CLR可能新建一个Object而不是直接将其分配给变量。根据GC,这个对象将是一个准备收集的死对象。当发生这种情况时,编译器将指示GC尚未运行GC。

    这是msdn上的博客文章,其中包含更多信息:http://blogs.msdn.com/b/abhinaba/archive/2009/09/02/netcf-gc-and-thread-blocking.aspx

    编辑:嗯,先生,我错了#4。请参阅“安全点”部分中的here。如果我们在p / invoke(非托管)代码部分中,则允许它运行,直到它再次返回到托管代码。

    然而,根据this MSDN article,如果我们处于CLR代码的非托管部分,那么它不被认为是安全的,它们将等到代码返回托管。 (至少我很亲密。)