C# 垃圾回收
Posted
技术标签:
【中文标题】C# 垃圾回收【英文标题】:C# Garbage collection 【发布时间】:2011-11-29 03:03:53 【问题描述】:假设我们有:
public void foo()
someRefType test = new someRefType ();
test = new someRefType ();
垃圾收集器如何处理第一个堆对象?是否在新分配之前立即收集垃圾?一般机制是什么?
【问题讨论】:
你试过这个(google.com/search?q=how+c%23+garbage+collection+works)吗?真的,这会给你一堆高质量的解释,就在列表的顶部。 【参考方案1】:垃圾收集器如何处理第一个堆对象?
谁知道?这不是确定性的。可以这样想:在具有无限内存的系统上,垃圾收集器没有做任何事情。你可能认为这是一个不好的例子,但这就是垃圾收集器为你模拟的:一个具有无限内存的系统。因为在可用内存比程序所需的足够多的系统上,垃圾收集器永远必须运行。因此,您的程序无法对何时收集内存(如果有的话)做出任何假设。
所以,您的问题的答案是:我们不知道。
在新分配之前是否立即收集垃圾?
没有。垃圾收集器不是确定性的。你不知道它什么时候会收集和释放垃圾。您不能对何时收集垃圾或何时运行终结器做出任何假设。
事实上,它不太可能被这么快收集(这会使收集过于频繁)。此外,在具有足够内存的系统上,垃圾收集器从不 必须运行。
一般机制是什么?
这是一个相当广泛的问题。但其基本原理非常简单:垃圾收集器模拟一台内存无限的机器。为此,它以某种方式跟踪内存并能够确定内存何时是垃圾。当它认为合适时,由于需要模拟无限内存,它会不时收集这些垃圾并使其再次可用于分配。
【讨论】:
或者更准确地说“我们不知道”。【参考方案2】:不,没有任何内容表明该对象被立即收集。事实上,这不太可能。它最终会被垃圾收集器收集,但你无法确切知道何时。
您可以通过调用 GC.Collect
来强制收集,但通常不建议这样做。
垃圾回收的具体工作原理是一个相当大的主题,但是您可以read on MSDN 找到很好的文档。
【讨论】:
【参考方案3】:有许多不同的垃圾收集策略,这些年来它们变得更加复杂和高效。文献和网络上有很多关于它们的优秀资源。但我也发现有时一个不完美且色彩丰富的比喻给了我一种直觉,帮助我开始。所以请允许我试一试:
.NET 有一个所谓的“分代”垃圾收集器,我认为它的行为就像我自己一样。我让脏衣服和邮件(“C# 对象”)在我的客厅地板上堆积了几天(“内存”),当我发现我再也看不到地毯时(“内存已满” )我花了一些时间清理(“垃圾收集”)起居室(“0代”),扔掉不再需要的物品(“不再可用”)并将剩余的物品移到我的卧室( “第一代”)。很多时候,这为我争取了一些时间,我不需要再做任何工作了。但是当我的卧室填满时,我会做类似的事情,扔掉一些物品并将其他物品移到我的地下室(“第 2 代”)。有时甚至地下室也会被填满,然后我遇到了真正的问题,需要进行一些大的春季大扫除(“完整收集”)。
将这个比喻应用到您的示例中,我们可能会猜测第一块垃圾(“堆对象”)只是闲置,直到我有时间捡起它(“运行第 0 代收集器”),当我感觉喜欢它,当地板被完全覆盖时,或者永远不会:-)
【讨论】:
【参考方案4】:要查看对象何时被删除,您可以覆盖类中的finalize 方法以打印何时以及哪些对象被删除,如下面的示例所示:
class MyClass
private int _id;
public MyClass(int id)
_id = id;
~MyClass()
Console.WriteLine("Object " + _id + " deleted at " + DateTime.Now + " .");
class Program
static void Main(string[] args)
MyClass p1 = new MyClass(1);
p1 = new MyClass(2);
Console.ReadKey();
要强制垃圾收集器更快地释放这些对象,您可以将一个字段作为长数组添加到它们,例如 private int []memory;
并在构造函数中:memory=new int[10000000]
。
【讨论】:
以上是关于C# 垃圾回收的主要内容,如果未能解决你的问题,请参考以下文章