在上一篇中,讨论了字符串常量的拘留池和不可变性;对于字符串变量,没有这个特性(或其他DotNet的非托管资源),当我们使用完后就要手动回收,即将变量的值指向null(p=null),然而堆内存中,那个没有任何变量引用的对象并没有立即回收(还占用一定量的堆内存),所以当我们要进行一个相当耗时且最好不要中断的操作时,最好调用垃圾回收,回收内存中的“垃圾”(没有变量引用的对象和非托管资源)以保证内存足够使用,这里提一下,所谓非托管资源,指的是非Dotnet开辟的资源,用完后再调用释放资源,如:数据库连接中的SqlConnection,SqlCommand等对象,用完要调用Dispose()释放,通常使用这类对象用using(),保证离开using范围,对象被回收。

接下来,说一下垃圾回收机制(垃圾回收机制只回收托管堆中的内存资源),在DotNet中有“代”的概念(共3代),举例说明:

aaarticlea/png;base64,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" alt="" />

同时,我们假设第0代大小为256M,第1代是512M,第2代是1G。程序执行一段时间后,定义了3个变量d、e、f,第1代中b指向null,但是第0代放不下,那么Dotnet会提升第0代中存活变量的代,结果如下:

aaarticlea/png;base64,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" alt="" />

程序继续执行一段时间,变量C又指向null,同时定义3个变量g,h,i,DotNet看到第0代放不下,继续提升第0代变量的代同时将新变量放入第1代

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfkAAAAuCAIAAACkmPeQAAACF0lEQVR4nO3aUU7DMBBF0e5/0/BRqVRgEKkn9fPknG/qOLF7SaLePgDo7rZ6AgCcTusB+tN6gP60HqA/rQfoT+sB+tN6gP60HqA/rQfoT+sB+tN6gP6+Wn8DYEOHW1//r4Q8FvoiLPRFaD1jFvoiLPRFaD1jOQu9aiY5V+BUOaeZM5O7tPlM0nrGchZa60+Vc5o5M7lLm88krWcsZ6G1/lQ5p5kzk7u0+UzSesaqFvr/PwA4eyZvOO6hHzyEyJnt/D6pPZdDo+Wvu9YzVrjQF2n94+/3+o7kzHZ+Jlr/B61nTOtfbv1ecqa9devzpbR+x4ff3koeqEuW9YXbq5K99P8RCk/2/TZd6D9GWLgBJo94qojWP48Zfr2uY2Yhvn32bQlYddySw61StdAJd+XfgmsDPIto/WPk/P+N17Fp6xfeZm66dZu1vnDAZhsgpfWPYcOv13Vs2vqZA02OtunWrXqHs3wmP0fQ+mcRrfcOJ5DWN/uq/6ZwoRfOZDiC1j/TesYKH+29r09WdV/vHU74Boho/cfmv2RoqfDRfnJND312SXq23r07PsD99vHn6z+/HM02QErrSZOz0KtmknMFTtWm9eXS5jNJ6xnLWWitP1Wndzi10uYz6ZXWA7CdY60HoCutB+hP6wH603qA/rQeoD+tB+hP6wH603qA/rQeoD+tB+hP6wH603qA/rQeoD+tB+hP6wH6+wTBYYOLC1vxHAAAAABJRU5ErkJggg==" alt="" />

依次类推,直至3代的内存消耗殆尽,此时DotNet会提升3个代的存储空间,保证变量能放进去。直至提升代的空间后,仍放不下,此时就内存溢出,抛异常了。当我们开始就定义一个大对象---1G的对象),将被直接放入第2代。

了解了代的概念,开始上代码:

  Person p = new Person() { ID = , Name = "张三", BirthDate = DateTime.Now };  //对象初始化器
p = null;
GC.Collect();
Console.WriteLine(p.ID+"=="+p.Name+"=="+p.BirthDate);

GC.Collect()就是告诉DotNet,请垃圾回收一把。这时,DotNet会将程序暂停,保存变量的当前状态,进行垃圾回收,回收完毕,重新分配内存,让程序继续执行(因为程序会暂停执行,所以对性能会有影响,所以一般不建议经常调用GC.Collect()来执行垃圾回收),上面的代码会抛空引用异常。

弱引用,指的是一个变量可以被垃圾回收了。这个对象不会用了,但是日后又担心会用,而且这个对象的创建非常耗时,我们就要用弱引用引用起来,需要注意的是,弱引用引用起来的对象是可以被垃圾回收的,但只要没被垃圾回收(能引用得到),就可以继续使用。

 Person p = new Person() { ID = , Name = "张三", BirthDate = DateTime.Now };  //对象初始化器

             WeakReference wReference = new WeakReference(p);        //将p对象弱引用起来
p = null; GC.Collect(); //手动调用垃圾回收
object o = wReference.Target;
if (o!=null&&wReference.IsAlive)
{
Person p1 = o as Person;
Console.WriteLine(p1.ID + "==" + p1.Name + "==" + p1.BirthDate);
}
else
{
Console.WriteLine("对象被垃圾回收了,请重新创建对象吧");
}

运行可知aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAS0AAAAlCAIAAACYpShgAAAEBUlEQVR4nO2by3EbMRBENxxGpnyYiULYoyLwlYHw4oNUWzAw3dP4kLDL/Q4uChg0GvORVS75eBrzFr7ut4/Px88Xj8+P2+12/xLPPj4/cPTX/VYo/5scuw2Y/4fv4fuha3I8h8aYl+M5NGY/nkNj9uM5NGY/nkNj9uM5NGY/x/P5/GWM2crPHB4Z53kObM2LVOvpXbqZYXotvZkxP2L+Jw0oamv9Dwu+m8k5PAEDOuI6T+v3rugKhfFXiHOYivOHpPRmUjHZKxhuDVS/N0Y/NZz55fVKmJnDJa3QK8XFy910YHSp8stUVmFJUUtLSsN1NRZS48evmC7D5DoRYkYPrvy0nnU/3VxzmJaQ+EagYK7A7+WcYA676hTuhvUYq82qig48at6GmLQwS4phFNzbJ0lrYoVz7xxWXG5C95XX0Cjy3VWqcj1NJdJEZpB46qRcTC0RhwvhTlD20lPtZ+I/zRiql+hHPFjuKvZCk4r5lfA5RF+2iyjF4pH28UoxyuOoGMgJCkCn0sKIJnnMPPoVSmTb0GkyyXGlScS+X96ff9EcduXrEL7LhkeO6epyS+1nZCl8bzpmvU/QA3Sq5+hVmAwLt44iG6HgmaUU3di+OtQJV9K0IDPnn5Ull66k+vtwzESYNRR20u5pj4SfkSUSTxTCU13ByA+5fZ4BwQHzSh5E8WqRzwMx84r+rKSU5lxJ+3NpmBdkovSnzAD6k58ixvR4opA2TRqM/JDb50FtTfomDONNpuQh9KMcOYo2EC2FfkhwWrjQZNo8ixmewypTZVj6SKScPp5XtA3oSj2/omyXcD30E163iq7U8SOovu1gkBKk4qklFJPGT/Zna3J5sRL4z6XVekj54LZNiY7yclQkdAtqmvBIZbs8GF4d+tTLtry01etawiMI0TYpQZkKUmiuw7OEss39V4UmYajKLyecw9ZH+PLqVcobSCV436T2WjOKOPIZXoFOiTVLw/g8cMEBV2JAlUAlD2LqyoZB9F5RiVcpUpqBxJD1WcJ/L23vS1sWVauNTD8fURLLMJ7HUC01o++G4kp50pjwyakgaeVQnxC6RQ2KqkNWBo6gLbHE125qXrTRVaAOyt+nIWHEFspOeCRMRNjKYj3SgFD82tL7kogPuJqJKYO7pkIPUN44P4dXaZQ0vqc/J22Mk/5+KRqS8IVhWKsWfmiPt9cp0zLTN8ruQOuHydFvVOJ5LXgCUT5DHe4WqXEp7lBJAlJTwojygJ9BlN/zFu9Wwqp0tEdWvTNM2ZI8hhWtdvX1VbQdtlx28goiNcnC/tyG+P8tjDEvxHNozH48h8bsx3NozH48h8bsx3NozH48h8bsx3NozH48h8bsx3NozH48h8bsx3NozHZ+A7XFh24Ws3HHAAAAAElFTkSuQmCC" alt="" />。这是因为我们手动调用了GC.Collect(),把这句话注释掉,再运行,

Person p = new Person() { ID = , Name = "张三", BirthDate = DateTime.Now };  //对象初始化器

            WeakReference wReference = new WeakReference(p);        //将p对象弱引用起来
p = null; //GC.Collect(); //手动调用垃圾回收
object o = wReference.Target;
if (o!=null&&wReference.IsAlive)
{
Person p1 = o as Person;
Console.WriteLine(p1.ID + "==" + p1.Name + "==" + p1.BirthDate);
}
else
{
Console.WriteLine("对象被垃圾回收了,请重新创建对象吧");
}

运行结果如下:

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOAAAAAnCAIAAACZotO6AAAB3UlEQVR4nO2aQXLEIAwE/f9X8Yp8JpccUuWKQRKDsDFJuk+skMVITNmXPT4BNuZ4WwBABAaFrcGgsDUYFLbm+ADYmONRSinPHgAgUq6cwSpnuS6ABtGgRWONZvhHmAbFajDFjQZqDfqKO73XcPyGDqQqb/T0R8BUkviMJEbtHSEercx5VFJSilLkZ6nvxYvujNfdn23B2L6jBYO0QHNA4h69vkRvKXOeclfrqjRmk5M10+iD+2ksbw7dKVV1TBlBfps2esGifvGpbnxIp6K/Q1d9q8OMB8+aPcdp3nREPWZ35zrQ4z1u7gbxbkGlQndXyQzm2T4V9OtNWDld0e9yQwn/DTpfeYZg+sGuGRHdFm/dUsQjZ2VlnTs6NvQAcfXqGCV+RqrFvEhdj9lXlTaUr9SPt7z80biHnu/1FfebO3e0i2dKXKt5i5UEFinOS2Jo0He5M5EvKqziQ6ebcbNOV+cvMOix3KOeC2OT6QYdsvJkvn476w2qzHnKXaUhWehas1qYPx8l6MuMd+dQbcW9mFc7pHP0XtL36D0ilgrOTYhZRLkatBJ9LnSWqoe/imnH1l4YDl6j/Uy8owMAAAAAAAAAAAAAAAAAAAAATPiHG2wNBoWtwaCwNRgUACDJF0+7dI3jhsz9AAAAAElFTkSuQmCC" alt="" />

由此可见,虽然将p指向了null,但是因为还没被回收,我们通过弱引用(WeakReference)能找到它,便可继续使用。

在使用弱引用时,要注意:

一定是先object o = wReference.Target; 将对象强引用起来,再加判断,如果先判断wReference.Target != null,再执行object o = wReference.Target时正巧p被垃圾回收了,那么o就是null。

弱引用的适用场景:

1.创建一个对象非常耗时;

2.这个对象不会用了(可以被垃圾回收),但是日后又担心会用;

3.弱引用的对象也不是一定就存在,如果手动调用GC.Collect()或者正好被垃圾回收,也会引用不到,此时若要用,只能重新创建对象。

C#的垃圾回收机制及弱引用的更多相关文章

  1. java中垃圾回收机制中的引用计数法和可达性分析法(最详细)

    首先,我这是抄写过来的,写得真的很好很好,是我看过关于GC方面讲解最清楚明白的一篇.原文地址是:https://www.zhihu.com/question/21539353

  2. 详解python的垃圾回收机制

    python的垃圾回收机制 一.引子 我们定义变量会申请内存空间来存放变量的值,而内存的容量是有限的,当一个变量值没有用了(简称垃圾)就应该将其占用的内存空间给回收掉,而变量名是访问到变量值的唯一方式 ...

  3. PHP垃圾回收机制

    一.引用计数基本知识 每个php变量存在一个叫"zval"的变量容器中,当一个变量被赋常量值时,就会生成一个zval变量容器.一个zval变量容器,除了包含变量的类型和值,还包括两 ...

  4. 【Python】 垃圾回收机制和gc模块

    垃圾回收机制和gc模块 Py的一个大好处,就是灵活的变量声明和动态变量类型.虽然这使得学习py起来非常方便快捷,但是同时也带来了py在性能上的一些不足.其中相关内存比较主要的一点就是py不会对已经销毁 ...

  5. PHP内核之旅-6.垃圾回收机制

    回收PHP 内核之旅系列 PHP内核之旅-1.生命周期 PHP内核之旅-2.SAPI中的Cli PHP内核之旅-3.变量 PHP内核之旅-4.字符串 PHP内核之旅-5.强大的数组 PHP内核之旅-6 ...

  6. python之MRO和垃圾回收机制

    一.MOR 1.C3算法简介 为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性的问题. python2.3版本之后不管是新式类还是经典类,查找继承顺序都采用C3算法 2.算法原理 C3算法的 ...

  7. python的内存管理与垃圾回收机制学习

    一.python内存申请: 1.python的内存管理分为六层:最底的两层有OS控制.第三层是调用C的malloc和free等进行内存控制.第四层第五层是python的内存池.最上层使我们接触的直接对 ...

  8. 【第1题】 Pythonn内存管理以及垃圾回收机制

    内存管理 Python解释器由c语言开发完成,py中所有的操作最终都由底层的c语言来实现并完成,所以想要了解底层内存管理需要结合python源码来进行解释. 1. 两个重要的结构体 include/o ...

  9. 补充:垃圾回收机制、线程池和ORM缺点

    补充:垃圾回收机制.线程池和ORM缺点 垃圾回收机制不仅有引用计数,还有标记清除和分代回收 引用计数就是内存地址的门牌号,为0时就会回收掉,但是会出现循环引用问题,这种情况下会导致内存泄漏(即不会被用 ...

随机推荐

  1. ZOJ 3790 Consecutive Blocks

    大致题意就是给你一个数列,让你最多移除K个数字,使得连续的相同数字的长度最大,并求出最大长度. 我们将此序列按颜色排序,颜色相同的话按位置排序,那么排完序之后颜色相同的blocks就在一起,只是他们的 ...

  2. Warning: Function created with compilation errors!

    解决方案: sqlplus / as sysdba grant execute on UTL_I18N to scott; grant execute on DBMS_CRYPTO to scott;

  3. NOIP2002 矩形覆盖

    题四 矩形覆盖(存盘名NOIPG4) [问题描述]: 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2), ...

  4. Clean Code–Chapter 7 Error Handling

    Error handling is important, but if it obscures logic, it's wrong. Use Exceptions Rather Than Return ...

  5. Weka 入门3

    这次我们介绍Evaluation类.在上一次中我们只是单纯的预测了分类值,并没有其他评价数据.这场我们使用Evalution类.首先初始化一个Evaluation对象,Evaluation类没有无参的 ...

  6. Xcode部分插件无法使用识别的问题

    1. 首先查看 Xcode 的 UUID,在终端执行 defaults read /Applications/Xcode.app/Contents/Info DVTPlugInCompatibilit ...

  7. new Date() iso不支持兼容性问题

    在IOS5以上版本(不包含IOS5)中的Safari浏览器能正确解释出Javascript中的 new Date('2013-10-21') 的日期对象. 但是在IOS5版本里面的Safari解释ne ...

  8. JBPM学习(四):执行流程实例

    概念: ProcessInstance,流程实例:代表流程定义的一次执行.如:张三昨天按请假流程请了一次假.一个流程实例包括了所有运行阶段,其中最典型的属性就是跟踪当前节点的指针,如下图. Execu ...

  9. JBPM学习(三):管理流程定义

    概念: ProcessDefinition,流程定义:一个流程的步骤说明,如一个请假流程.报销流程.是一个规则. ProcessDefinition,流程定义对象,是解析.jpdl.xml文件得到流程 ...

  10. Android架构分析之Android消息处理机制(二)

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本号:4.4.2 在上一篇文章中我们看了一个使用Handler处理Message消息的样例,本文我们 ...