标签:div 运行 lock 写代码 == border system mamicode 并且
这个问题涉及了GC的内部算法和机制,了解它的机制对程序员编写代码具有指导意义。对于这些算法,应该立即并且能够口述他们的基本原理。
在.NET中,引用类型对象实例通常通过引用来访问,而GC判断堆中的对象是否仍然在被使用的依据也是引用。简单来说:当没有任何引用指向堆中的某个对象实例时,这个对象就被视为不再使用。
了解了判断对象是否被使用的依据后,来看一下GC查看引用的算法。垃圾回收机制把引用分为以下两类:
垃圾回收时,GC从所有扔在被使用的根引用出发,遍历所有的对象实例,那些不能被遍历到的对象将被视为不再被使用而进行回收。为了更加直观地理解根引用和非根引用,下面的代码给出了一个实际的例子。
using System; namespace usingDemo { public class Root { public static Employee staticEmployee; static void Main(string[] args) { // 静态变量 staticEmployee = new Employee(); // 局部变量 Employee a = new Employee(); // 局部变量 Employee b = new Employee(); // 实例成员 a._boss = new Employee(); Console.Read(); Console.WriteLine(a); } } public class Employee { public Employee _boss; public override string ToString() { if(_boss == null) { return "没有BOSS"; } else { return "有一个BOSS"; } } } }
上面的代码中,一共拥有两个局部变量和一个静态变量,这些引用都是根引用。而其中一个局部变量a拥有一个成员实例对象,这个引用就是一个非根引用。下图展示了执行到Console.Read();这行代码时运行垃圾回收时的情况。
如上图所示,在代码中执行到Console.Read()时,存活的根引用有staticEmployee和a,前者因为它是一个公共静态变量,而后者是因为后续代码仍然使用a。通过这两个存活的根引用,GC会找到一个非根引用staticEmployee._boss,并且发现三个仍然存活的对象。而b的对象则将被视为不再使用而被释放。
这里GC侦测出b引用不再被使用从而释放了b的对象,更简单地确保b对象被视为不再被使用的方法是把b引用置为null,即b=null。
另外,当一个从根引用出发的遍历抵达一个已经被视为在使用的对象时,将结束这一个分支的遍历,这样做是为了避免死循环。
GC通过在使用的根引用遍历所有引用的对象实例。当一个对象不能被遍历时,将被视为不再被使用。
标签:div 运行 lock 写代码 == border system mamicode 并且
原文地址:https://www.cnblogs.com/dotnet261010/p/12331729.html