在.NET中的GC期间安全地暂停线程

Ost*_*tap 9 .net garbage-collection

.NET中的线程在GC期间暂停.如何通过CLR安全地暂停线程?像Win32 SuspendThread API一样以残酷方式停止线程会有什么风险?

Ale*_*x F 7

这是关于.NET Compact Framework,但我认为对于普通的.NET是正确的:http://blogs.msdn.com/b/abhinaba/archive/2009/09/02/netcf-gc-and-thread-blocking的.aspx

在实际运行GC之前,CLR尝试进入"安全点".每个线程都有一个与之关联的挂起事件,并且每个线程定期检查此事件.在启动GC之前,CLR枚举所有托管线程,并在每个线程中设置此事件.在线程检查并发现此事件集的下一个点,它阻止等待事件重置(这在GC完成时发生).


Jan*_*ray 5

通常,线程1可以安全地暂停线程2,通过设置"请立即暂停"标志,保证在线程2中执行代码在有限的时间段内进行测试,并且稍后在其执行中暂停其自身的安全点.

在.NET CLR(过去曾经是这种情况)中,线程可以处于协作GC模式或抢占模式.在协作模式下,例如在运行托管代码方法时,线程偶尔会明确地检查它是否应该产生.

相反,在抢占模式下,例如在运行p调用的本机代码时,有时在CLR本身(MSCORWKS.DLL等)时,另一个线程(包括需要GC的另一个CLR线程)可以单方面暂停第一个线程.指令边界.

实际上,这些可以结合起来.CLR GC可以设置"请立即暂停"标志,然后等待一段时间,以防先占模式线程返回到协作模式(然后测试标志并暂停其线程).如果在等待之后,抢先模式线程仍然没有挂起,则CLR(在另一个线程上)可能会单方面暂停它.

在协作模式下运行.NET方法,生成的本机代码依赖于协作模式非抢占保证,以最有效地操作对象存储器(GC堆等).如果您在外部并且"残酷地"在其执行中的任意点暂停协作GC线程,则可能使对象内存或其他CLR内部处于可能不适合正确的垃圾收集周期或其他CLR操作的状态.但这在实践中从未发生过,因为这不是协作模式线程的暂停方式.

(显然存在一些极端情况,例如当协作模式线程完成其OS线程调度程序量程时,OS上下文将该核心切换到其他某个线程.由于该线程不再运行,因此它不会轮询yield标志,并赢得'我不记得在这种情况下会发生什么 - CLR是否必须等到它被重新安排,测试标志和产量,或者它是否暂停线程然后检查它的IP以查看它是否在一个安全的地方.任何人?)

我相信这在SSCLI(转子)内部描述.

说得通?

快乐的黑客!