考虑这两个类:
public class A
{
B b;
public A(B b) { this.b = b; }
}
public class B
{
A a;
public B() { this.a = new A(this); }
}
如果我有像上面这样设计的类,这些类的对象会被垃圾收集器(GC)收集吗?
假设我这样做:
void f()
{
B b = new B();
}
在这个方法中,我创建了一个名为 b
的 B
实例,当方法返回时,b
超出范围,GC 应该能够收集它,但如果要收集它,它必须先收集 a
,它是 B
的成员,要收集 a
,它需要先收集 b
,它是 A
的成员。它变成圆形。所以我的问题是:这样的循环引用会阻止 GC 收集对象吗?
如果是,那么我们如何避免这个问题呢?我们如何确保在我们的类设计中没有循环引用?是否有任何工具(或编译器选项)可以帮助我们检测循环引用?
如果不是,我们在哪里以及为什么使用 WeakReference 类?它的目的是什么?
A
不能依赖于 B
,因为必须首先创建 A
,作为 B
的成员,因此 A
} 只能持有对 B
的弱引用。因此,先销毁 B
然后再销毁 A
是安全的。递归论证,每个计算机程序都必须如此。永远不可能有一个真正的、完全对称的循环依赖。
why do we use WeakReference class? What is its purpose?
我用它——例如——缓存数据(在字典中)。如果它还活着,很好,如果没有,我会在第一次请求时再次加载它。
.NET 垃圾收集器绝对可以处理循环引用。垃圾收集器如何工作的非常高级的视图是......
从局部变量、静态变量和 GC 固定对象开始。这些都不能收集
标记通过遍历这些对象的子对象可以到达的每个对象
收集所有未标记的对象。
这允许很好地收集循环引用。只要它们中的任何一个都无法从已知无法收集的对象中到达,那么循环引用本质上是无关紧要的。
注意:我意识到我遗漏了许多有趣的细节,以使这个答案简单直接
不,这不是问题,因为 GC 可以处理循环引用
MSDN 说
如果一组对象包含相互引用,但这些对象都没有直接或间接地从堆栈或共享变量中引用,那么垃圾回收将自动回收内存。
几个答案已经解释了循环引用不是问题。
至于弱引用 - 使用它们的原因是缓存。
当 GC 遍历对象依赖树时,他会忽略弱引用。换句话说,如果对一个对象的唯一引用是弱引用,它将被垃圾收集,但如果在创建引用和您尝试使用之间没有垃圾收集,您仍然可以访问该对象。
不,循环引用不会影响垃圾收集器,它将完全能够收集 B 的实例。
垃圾收集器知道超出范围后没有人可以引用B的实例,因此没有人可以使用B的实例间接引用A。
不定期副业成功案例分享