欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.NET垃圾回收器原理及使用

程序员文章站 2022-03-01 13:28:33
.net 应用程序中的垃圾回收器是什么?垃圾收集器只不过是 clr 提供的一个功能,可帮助我们清理或销毁未使用的托管对象。通过清理或销毁这些未使用的托管对象,它基本上回收内存。当dotnet应用程序运...

.net 应用程序中的垃圾回收器是什么?

垃圾收集器只不过是 clr 提供的一个功能,可帮助我们清理或销毁未使用的托管对象。通过清理或销毁这些未使用的托管对象,它基本上回收内存。

当dotnet应用程序运行时,它会创建多个对象,并且在给定时刻,应用程序可能不使用其中一些对象。

因此,对于这些对象,垃圾回收器作为后台线程连续运行,并在特定的时间间隔时间,它会检查是否有任何未使用的托管对象,以及它是否发现它只是清理这些对象并回收内存。

注:垃圾回收器将仅销毁未使用的托管对象。它不清理非托管对象。

.net垃圾回收器代数?

让我们了解什么是垃圾收集器代,它如何影响垃圾收集器的性能?

在.net中, 有三代。它们是第0代、第1代和第2代。

了解第0代、第1代和2代

假设您有一个名为 app1 的简单应用程序。应用程序一启动,就创建 5 个托管对象。

每当创建任何新对象(新对象)时,它们都会移动到称为"第 0 代"的存储桶中。为了更好的理解,请看下图所示:

.NET垃圾回收器原理及使用

我们知道垃圾收集器作为后台线程连续运行,以检查是否有任何未使用的托管对象,以便通过清理这些对象来回收内存。

现在,假设应用程序不需要两个对象(object1 和 object2)。因此,垃圾回收器将销毁这两个对象(object1 和 object2),并回收第 0 代存储桶中的内存。

但应用程序仍然需要其余三个对象(object3、object4 和 object5)。

因此,垃圾回收器不会清理这三个对象。因此,垃圾收集器将做的是,他这三个托管对象(object3、object4 和 object5)将移动到第 1 代存储桶,如下图所示。

.NET垃圾回收器原理及使用

现在,假设您的应用程序又创建了两个新对象(object6 和 object7)。作为新对象,应在第 0 代存储桶中创建它们,如下图所示。

.NET垃圾回收器原理及使用

现在,再次运行垃圾收集器,它涉及到第 0 代存储桶和检查使用的对象。假设应用程序未使用这两个对象(object6 和 object7),因此它将删除这两个对象并回收内存。

现在,它转到第 1 代存储桶,并检查哪些对象未使用。假设应用程序仍然需要 object4 和 object5,而不需要对象 3。

因此,垃圾收集器将做什么,它将摧毁 object3 并回收内存,以及它将 objec4 和 object5 移动到第 3 代存储桶,如下图所示。

.NET垃圾回收器原理及使用

什么是几代?

代不过是什么,它们将定义对象在内存中保留的时间。现在,你想到的问题是,为什么我们需要几代?

为什么我们需要几代?

通常,当我们使用大型应用程序时,它们可以创建数千个对象。因此,每个对象,如果垃圾回收器去检查他们真的是否需要,这是一个非常笨重的过程。

通过创建此类,如果第 2 代存储桶中的对象意味着"垃圾收集器"将减少对此存储桶的访问。

原因是,如果对象移动到第 2 代,则意味着它将在内存中停留更多时间。没有必要去检查他们一遍又一遍。

因此,简单地说,我们可以说第 0 代、第 1 代和 2 代有助于提高垃圾收集器的性能。第 0 代中的对象越好,性能越好,以最佳方式使用内存。

如何在类中使用析构函数,我们最终进入一个双垃圾回收器循环?

垃圾收集器将只清理托管代码。换句话说,对于任何类型的非托管代码,要清理这些代码必须由非托管代码提供,垃圾回收器无法控制它们来清理内存。

例如,假设您在 vb6 中有一个名为 myclass 的类,然后您必须公开一些函数,例如 cleanup(), 在该函数中,您必须编写逻辑来清理非托管代码。

从dotnet代码中,您只需调用该方法 cleanup()即可启动清理。这点,或要从其中调用清理的部分是类的析构函数。

这看起来是编写清理代码的最佳地点。但是,在析构函数中编写清理时,有一个与之相关的大问题。让我们了解问题出在哪里?

在类中定义析构函数时,垃圾收集器在处置对象之前,将转到类中提出问题,您是否有析构函数,如果您有析构函数,然后将对象移动到下一代存储桶。

换句话说,即使未使用析构函数本身,它也会清理具有析构函数的对象。因此,它将等待析构函数运行,然后它会去清理对象。因此,与第 0 代相比,第 1 代和第 2 代中的对象更多。

(示例)使用析构函数

创建一个控制台应用程序,然后在程序类中复制并粘贴以下代码。

.NET垃圾回收器原理及使用

注:如果在析构函数中编写清理代码,则最终将在第 1 代和第 2 代中创建更多对象,这意味着您没有正确使用内存。

如何克服上述问题?

通过使用所谓的最终处置模式可以解决此问题。

为了实现这一点,类应实现 idisposable 接口,并提供 dispose 方法的实现。在 dispose 方法中,您需要为非托管对象编写清理代码,最后需要调用 gc。通过将 true 作为输入值传递来抑制无限化(true) 方法。

此方法告诉抑制任何类型的析构函数,然后去清理对象。为了更好的理解,请看下图。

.NET垃圾回收器原理及使用

一旦您使用对象,然后您需要调用 dispose 方法,以便双垃圾回收器循环不会发生,如下所示。

.NET垃圾回收器原理及使用

完整的代码如下:

.NET垃圾回收器原理及使用

现在,想到的问题是,为什么析构函数在那里?原因是作为开发人员,您可能忘记在使用对象后调用 dispose 方法。在这种情况下,析构函数将调用,它将去清理对象。

到此这篇关于.net垃圾回收器原理及使用的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持。