口碑好的邯郸网站建设,国外网站怎么进入,网站开发一键上架淘宝,网站建站网站jp586 vip弱引用 当一个根指向一个对象时#xff0c;该对象不可能被垃圾收集器收集#xff0c;在这种情况下#xff0c;通常说存在一个该对象的强引用#xff08;strong reference#xff09;。垃圾收集器还支持弱引用#xff08;weak reference#xff09;的概念。弱引用允许垃圾…弱引用 当一个根指向一个对象时该对象不可能被垃圾收集器收集在这种情况下通常说存在一个该对象的强引用strong reference。垃圾收集器还支持弱引用weak reference的概念。弱引用允许垃圾收集器收集对象同时也允许应用程序访问该对象结果取决于时间。 如果对象的弱引用存在那么在垃圾收集执行后该对象的内存将被执行清理。另一方面要访问一个弱引用对象应用程序必须获取该对象的一个强引用。如果应用程序在对象被执行之前得到了它的强引用那么垃圾收集器将不再对该对象执行垃圾收集因为这时存在一个该对象的强引用。 下面代码展示了弱引用的使用
class Program { static void Main( string [] args) { SomeWeakReferenceMethod(); SomeStrongtReferenceMethod(); } static void SomeWeakReferenceMethod() { // 创建一个强引用对象 SomeClass o new SomeClass(); WeakReference wr new WeakReference(o); o null ; // 移除对象的强引用 o wr.Target as SomeClass; if (o null ) { // 出现过垃圾回收对象的内存已经被回收 Console.WriteLine( 已经被回收 ); } else { // 未出现垃圾回收 Console.WriteLine( 没有被回收 o.X.ToString()); } } static void SomeStrongtReferenceMethod() { // 创建一个强引用对象 SomeClass o new SomeClass(); o null ; // 移除对象的强引用 try { Console.WriteLine(o.X); } catch { Console.WriteLine( error ); } } } public class SomeClass { private int x; public int X { get { return this .x; } } public SomeClass() { x 5 ; } }
个人感觉弱引用机制有点像缓存将一些操作起来比较费时比如便利系统的硬盘的东西第一次获取之后暂时放入缓存中并且将其引用置为null来减少应用程序的压力但是放置在缓存中可以再次使用减少读取时的压力至于是否能够再次使用成功要看垃圾收集器。如果执行过垃圾收集弱引用的对象将会被回收掉当然就无法再次使用了。 System.WeakReference有两个公用构造器
public WeakReference(object target); public WeakReference(object target, bool trackResurrection);target表示要追踪的对象(上例中为SomeClass) trackResurrection表示是否要追踪对象的复苏换句话说就是对象在执行Finalize方法后是否还要追踪该对象对象执行Finlize后对象复苏了 。 将不追踪对象复苏的WeakReference称为短弱引用short weak reference而将追踪对象复苏的称为长弱引用long weak reference。如果一个对象没有Finalize方法长短弱引用是一样的最好不要使用长弱引用因为长弱引用在一个对象被执行终止后允许该对象复苏将会导致对象的状态不可预知。 一旦创建了对象的弱引用通常将该对象的强引用设置为null为了再次使用该对象需要将弱引用转换为一个强引用通过WeakReference的Target属性来完成的。如果target为null那么对象已经被执行了垃圾收集否则将会得到该对象的强引用。这时对象将不会被垃圾收集器收集了。
弱引用的内部机理 需要再次探究托管堆。托管堆中包含了两个内部数据结构来管理弱引用。即短弱引用表和长弱引用表。这两个表包含着一些指针他们引用着托管堆对象。 当创建一个WeakReference对象时它会在两个弱引用表中选择一个长短弱引用相应对应并在其中寻找一个空白插槽。该插槽的值将被设为我们希望追踪对象的地址---也就是new WeakReference构造的那个对象的地址弱引用表将不会认为是应用程序的根否则垃圾收集器将不能收集它们中的指针引用的对象。 垃圾收集器运行时发生的一系列事情
垃圾收集器构造一个可达对象的图.net框架读书笔记---CLR内存管理\垃圾收集一垃圾收集器扫描短弱引用表如果表中的对象不是前面可达对象图的一部分对象已经不是根在上面的例子中o已经被置为null了那么表示该对象是一个不可达的对象将短弱引用表中对应插槽的值将被设置为nullTarget为null了垃圾收集器扫描终止化链表.net框架读书笔记---CLR内存管理\垃圾收集二。如果该链表中指针引用的对象不是可达对象图的一部分那么该对象将是不可达对象它将被从终止化链表转移到终止化可达队列上。这时对象由成为可达对象图的一部分了。垃圾收集器扫描长弱引用表如果表中的对象不是前面可达对象图的一部分该图现在已经包括终止化可达队列中引用的对象了那么表示该对象是一个不可达的对象将长弱引用表中对应插槽的值将被设置为nullTarget为null了垃圾收集器压缩内存填充不可达对象空出的位置。继续分析代码
if (o null ) { // 出现过垃圾回收对象的内存已经被回收 Console.WriteLine( 已经被回收 ); } else { // 未出现垃圾回收 Console.WriteLine( 没有被回收 o.X.ToString()); }
因为在此之前o已经被置为null了所以它已经是一个不可达对象如果执行垃圾收集器o自然不在可达对象图中那么垃圾收集器将会将短弱引用表中插槽对应的值设为null这样Target将返回null上面代码自然会执行if里面的代码。如果垃圾收集器还没有执行虽然o已经为null但是短弱引用插槽依然保存着对象的引用那么Target将会返回对象的引用使对象继续可达可以使用当然上面代码就会执行else里面的代码。 短弱引用并不追踪对象的复苏。只要垃圾收集器判断对象成为不可达的对象它就会把短弱引用表中对应的指针设置为null。如果对象重写了Finalize方法那么这时该方法还没有被调用所以对象仍然存在。此时target仍然返回null虽然这时对象已经进入终止化可达队列对象仍然存在。