CLR Via C#读书笔记——垃圾收集相关知识点【2011-01-20】
来源:互联网 发布:直播软件你懂得 编辑:程序博客网 时间:2024/05/21 05:44
在现实世界中,经常会出现多个线程同时访问托管堆的情况,或者至少会有多个线程同时操作托管堆中分配的对象。当某个线程触发垃圾收集器时,其他线程就不能再访问任何对象(包括各线程自己堆栈上的对象引用),这是因为垃圾收集器可能会移动这些对象,改变它们内存地址。
因此当垃圾收集器开始运行时,所有执行托管代码的线程都必须被挂起。CLR使用几种不同的机制来确保安全的挂起线程,以便执行垃圾收集。CLR中存在多种机制的目的是为了尽可能地让线程保持运行,并且尽可能地减少开销。
当CLR开始执行垃圾收集时,它会立即挂起进程中所有正在执行托管代码的线程。接着,CLR会检查每个线程的指令指针以判断线程线程执行到哪里。然后,CLR将指令指针地址和JIT编译器产生的表做比较,从而确定线程正在执行的代码。
如果线程的指令指针位于某个表中标记的偏移之处,那么该线程将被认为是到达了一个安全点(safe point)。一个安全点指的是可以在垃圾收集执行完之前一直挂起线程的地方。如果线程的指令指针没有位于某个内部方法表中标记的偏移之处,那么该线程就没有到达一个安全点,CLR也就不能执行垃圾收集。在这种情况下,CLR会劫持该线程:CLR会修改线程的堆栈,以使它返回的地址指向CLR内部实现的一个特殊函数。然后,该线程将被允许继续执行。目前正在执行的方法返回时,CLR内部的特殊函数将执行,从而挂起该线程。
然而,线程有时候并不能很快从当前的方法中返回。所以在线程继续执行后,CLR会等待被劫持的线程大约250毫秒。过了这个时间之后,CLR会再次挂起线程,并检测其指令指针。如果线程达到了一个安全点,垃圾收集就可以开始执行了。如果线程仍然没有到达一个安全点,CLR将检测该方法内部是否又调用了其他的方法。如果确实调用了其他的方法,CLR将再一次修改线程的堆栈,以使线程在最近执行的方法中返回时能被劫持。然后,线程被允许继续执行,CLR会再等一段时间,之后会再次尝试劫持线程。
当所有的线程都到达了一个安全点或者被劫持后,垃圾收集才可以开始执行。当垃圾收集完成后,所有的线程将被允许恢复执行,应用程序也将继续运行。被劫持的线程也会返回到原来调用它们的方法中。
前面提到的算法还有一个小问题。即当CLR希望执行垃圾收集时,CLR就会挂起所有正在执行托管代码的线程,但是CLR没有挂起那些正在执行非托管代码的线程。一旦所有正在执行托管代码的线程到达了一个安全点或者都被劫持,CLR就允许垃圾收集开始执行。而执行非托管代码的线程允许继续执行,因为非托管代码正在使用的所有对象都是已经被固定了。如果一个正在执行非托管代码的线程返回托管代码,那么该线程就会被立即挂起,直到垃圾收集完成。
最终结果证明,CLR大部分时候都是使用劫持来挂起线程,而不是根据JIT编译器生成的表来判断线程是否到达了一个安全点,然后再决定挂起线程。这样做的原因在于,使用JIT编译器生成的表时需要更多的内存,并且增加了进程的工作集,这最终会极大地影响垃圾收集的性能。因此,JIT编译器生成的表中包含的信息适用于这样的场合:方法中包含循环语句,并且该循环中不调用其他的方法。如果方法中的循环调用了其他方法,或者方法没有循环,那么JIT编译器生成的表中就没有多少信息,因此CLR还是使用劫持来挂起线程。
- CLR Via C#读书笔记——垃圾收集相关知识点【2011-01-20】
- CLR Via C#读书笔记——垃圾收集(Timer)【2011-01-18】
- CLR Via C#读书笔记——CLR分配内存【2011-01-17】
- 属性——CLR via C# 读书笔记
- 泛型——CLR via C# 读书笔记
- CLR Via C#读书笔记——可空值类型操作符运算【2011-01-14】
- CLR Via C#读书笔记——Finalize方法被调用的时机【2011-01-18】
- CLR Via C#读书笔记——using语句【2011-01-19】
- CLR Via C#读书笔记——StreamWriter中的依赖问题【2011-01-19】
- clr via c#读书笔记
- CLR via C#读书笔记
- CLR Via C# 第四章 类型基础——读书笔记
- CLR via C#垃圾回收
- CLR Via C#读书笔记——Monitor类同步线程【2011-02-10】
- CLR Via C#读书笔记——接口约束【2010-01-09】
- CLR via C# 读书笔记目录
- CLR Via C# 第一章(CLR的执行模型)——读书笔记
- CLR via C# —— 线程
- 用Ant和JUnit构建自动化测试
- Android.mk文件用法与基础
- Monitoring WebLogic using JMX
- 随机数思考: rand()与arc4random()比较
- 懒加载异常org.hibernate.LazyInitializationException: could not initialize proxy - no
- CLR Via C#读书笔记——垃圾收集相关知识点【2011-01-20】
- volatile 变量使用指南
- 用 JProfiler4 调优 Weblogic 和 Tomcat 的视频
- xp下让iis支持asp.net (转载)
- 颜色16进制代码表-显示和16进制数值对比显示方便查找
- IE8 一窗多浏览
- 总结一个技巧 通过图片查找资料
- CREATE CACHE GROUP用法
- 测试