• GC垃圾回收


      我们在开发需求的时候,可能很少关注到垃圾回收,因为我们绝大多数的时候都是使用的托管资源,托管资源的内存回收.net已经帮我们做了,但是.net的内存回收不是实时的,所以我们还是要关注下.net的垃圾回收。

    什么是GC

    GC即Garbage Collection,用一句话总结就是:.net内置的一种垃圾回收机制。
     

    为什么要有GC

    既然知道GC就是.net内置的垃圾回收,那为什么要有GC呢?
    实际上在C语言(非托管)中,垃圾回收是由开发人员自己负责的,虽然这样看起来很灵活,但是存在两个问题:
    1,忘记释放或使用已释放的内存都会带来严重的bug。
    2,浪费开发人员的精力,使其无法集中精力关注业务,影响开发效率。
     
    所以,在C#(托管)中,微软引入了GC垃圾回收机制,使得开发人员从枯燥的垃圾回收的工作中解放出来,更加专注于业务。
     
    解释下托管资源和非托管资源:
    1,托管资源,可以简单理解为c#中的引用类型,比如Class,Interface等,如下图。

    可能有人会有疑问,那值类型呢?在.net中,因为值类型在内存栈上,超过作用域就自动出栈了,也就不存在所谓的垃圾的概念。

    2,非托管资源,最常见的比如数据库连接。

    垃圾回收算法 

    .net中常见的垃圾回收算法有两种。
    1,Mark-Sweep-Compact算法
    简单地把.NET的GC算法看作Mark-Compact算法。阶段1: Mark-Sweep 标记清除阶段,先假设heap中所有对象都可以回收,然后找出不能回收的对象,给这些对象打上标记,最后heap中没有打标记的对象都是可以被回收的;阶段2: Compact 压缩阶段,对象回收之后heap内存空间变得不连续,在heap中移动这些对象,使他们重新从heap基地址开始连续排列,类似于磁盘空间的碎片整理。
    回收过程如下图。
     
     
    2,Generational 分代算法
    .net将内存的托管堆分成了三个代龄,Gen 0,Gen 1,Gen 2 
    如果Gen 0 heap内存达到阀值,则触发0代GC,0代GC后Gen 0中幸存的对象进入Gen1,如果Gen 1的内存达到阀值,则进行1代GC,1代GC将Gen 0 heap和Gen 1 heap一起进行回收,幸存的对象进入Gen2。
     
     

    Dispose模式和using语句

    虽然看起来.net的GC机制看起来很完美,但是仍然存在两个问题:
    1,GC只能释放托管资源,并不能释放非托管资源。
    2,GC并不是实时的,所以就会造成性能上的问题。
     
    既然GC并不是实时的,那么它在哪些情况下会触发回收呢,有以下情形:
    1,第0代满时。
    2,代码显式调用了GC.Collect方法时。
    3,windows报内存不足时,比如OutOfMemory异常。
    4,CLR卸载AppDomain时。
    5,CLR关闭时。一个进程正常终止时(相对于通过任务管理器关闭),CLR就会关闭。
     
    所以为了弥补GC的不足,.net给我们提供了Dispose模式保证资源的及时释放。
    使用Dispose模式只需两步:
    1,自定义类型继承IDisposable接口,并实现接口中的Dispose方法。如下图。

    2,在代码中显式调用RabbitMQWrapper实例的Dispose方法,如下图。

    通常我们将调用Dispose方法放在异常处理的finally块中,这样可以保证清理资源的代码得到执行。

    为了简化这一操作,.net为我们提供了using语句,语法如下代码:

    1 using(var proxy= new RabbitMQWrapper())
    2 {
    3     //业务代码
    4 }
     
  • 相关阅读:
    《构建之法》读书笔记六
    《构建之法》读书笔记五
    《构建之法》读书笔记四
    《构建之法》读书笔记三
    《构建之法》读书笔记二
    《构建之法》读书笔记一
    开发mis系统需要的技术
    java异常处理
    多态
    动手动脑6
  • 原文地址:https://www.cnblogs.com/mcgrady/p/7117358.html
Copyright © 2020-2023  润新知