zoukankan      html  css  js  c++  java
  • 【转】.NET垃圾回收的机制解释

    首先,对象分为值类型和引用类型,值类型在用完后是由操作系统自动回收的,引用类型由垃圾回收器回收,所以提到垃圾回收肯定是对引用类型来说的。

    垃圾回收机制是为了解决内存泄漏问题,即对象在用完后,其占用的内存没有被释放,使一个无用的对象不必要的占用了内存,导致不正常的内存减少甚至耗尽。以前有两种内存管理技术,一种COM开发人员熟悉的引用计数技术,一种C++开发人员熟悉的Delete语句,COM开发人员会遇到循环引用的问题,C++开发人员可能忘记Delete,这都会导致内存泄漏。

    垃圾回收器在两种情况下会进行回收,一是自动在适合的时间运行(如内存被耗尽,或Cpu空闲时),一种是显式调用GC.Collect()来运行。因为在运行时,它会挂起当前运行的所有线程,所以除非使用了大量的非托管资源或内存大量减少,并且此时已不再需要那些非托管资源,一次性全部释放这些资源很有意义时,才显式调用GC.Collect()。

    垃圾回收器的执行过程是:

    1.在new一个对象的时候,如果这个对象实现了Finallize方法,GC就会在Finallization队列放一个指向此对象的指针。

    2.当垃圾回收器进行内存回收时,对于找到的每一个需要被回收的对象,会先在Finallization队列中查找是否有指向该对象的指针,如果有则将该指针移到Freachable队列,没有则直接回收。

    3.当Freachable队列非空时,激活某特殊线程,逐一执行队列中每个对象的Finallize方法,然后从本队列中删除对象指针,使对象变为像没有实现Finallize方法一样(即在Finallization队列中没有指针指向它)的对象,它们将在下一次垃圾回收时进行回收。

    4.按一定算法整理内存,在保证效率的情况下,使内存尽量连续。

    从上面可以看到实现了Finallize方法对象比没有实现的对象在垃圾回收时效率低,所以应该尽量避免不必要的Finallize实现。

    在C#中,实现Finallize的方法是使用析构函数语法,析构函数在编译时会被转换成Finallize。在Finallize方法只能释放非托管资源,因为该方法执行的时机不确定,所以当执行时,用到的托管资源可能已经被回收,如果再引用就会出错。

    对于需要资源回收的对象,为了提高垃圾回收效率,应该尽量实现IDisposable接口,并在Dispose方法中调用GC.SuppressFinallize(this),把对象的指针从Finallization队列删除,来防止GC调用Finallize方法。

    以下代码是推荐的实现IDispose接口的方法:

    View Code
    public class MyBase : IDispose
      2
      3{
      4
      5               private Component components;
      6
      7               private IntPtr handle;
      8
      9               private bool disposed;
     10
     11               public void Dispose()
     12
     13               {
     14
     15                   if(!disposed)
     16
     17                   {
     18
     19                       Dispose(true);
     20
     21                       GC.SuppressFinallize(this);
     22
     23                   }
     24
     25               }
     26
     27               protected virtual void Dispose(bool disposing)
     28
     29               {
     30
     31                   if(!disposed)
     32
     33                   {
     34
     35                       if(disposing)
     36
     37                       {
     38
     39                           if(components!=null)
     40
     41                               components.dispose();
     42
     43                       }
     44
     45                       CloseHandle(handle);
     46
     47                       handle=IntPtr.Zero;
     48
     49                       disposed=true;
     50
     51                   }
     52
     53               }
     54
     55               public void DoSomething()
     56
     57               {
     58
     59                   if(disposed)
     60
     61                   {
     62
     63                      throw new ObjectDisposedException();
     64
     65                   }
     66
     67               }
     68
     69               ~MyBase()
     70
     71               {
     72
     73                   Dispose(false);
     74
     75               }
     76
     77}
     78
     79public class MyDerive : MyBase
     80
     81{
     82
     83               private ManagedResource addedManaged;
     84
     85               private NativeResource addedNative;
     86
     87               private bool disposed;
     88
     89               protected override void Dispose(bool disposing)
     90
     91               {
     92
     93                   if(!disposed)
     94
     95                   {
     96
     97                       try
     98
     99                       {
    100
    101                           if(disposing)
    102
    103                           {
    104
    105                               if(addedManaged!=null)
    106
    107                                   addedManaged.Dispose();
    108
    109                           }
    110
    111                           CloseHandle(addedNative);
    112
    113                           disposed=true;
    114
    115                       }
    116
    117                       finally
    118
    119                       {
    120
    121                           base.Dispose(disposing);
    122
    123                       }
    124
    125               }
    126
    127}
    128
    129

    注意,以上代码不是线程安全的代码,如果遇到多线程,需要在if(!disposed)外层加上lock(this){}。

     

    转自周碧文 的博客,原文地址:http://www.cnblogs.com/kofzhoubiwen/archive/2008/06/28/1231641.html

     

  • 相关阅读:
    SharePoint Framework (SPFx) 开发入门教程
    SharePoint 2013 Designer 入门教程
    SharePoint 2013 开发教程
    SharePoint 2013 入门教程
    SharePoint Online 部署SPFx Web部件
    SharePoint Online SPFx Web部件绑定数据
    SharePoint Online 创建SPFx客户端Web部件
    SharePoint Online 配置框架(SPFx)开发环境
    SharePoint Online 创建应用程序目录
    SharePoint Online 启用 IRM
  • 原文地址:https://www.cnblogs.com/xiaoyusmile/p/2565963.html
Copyright © 2011-2022 走看看