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

     

  • 相关阅读:
    CF-478C
    HDU-2074-叠筐
    HDU-2037-今年暑假不AC
    POJ-2785-4 Values whose Sum is 0
    HDU-1160-FatMouse's Speed
    HDU-1297-Children’s Queue
    Redis客户端管理工具的安装及使用
    Redis客户端管理工具,状态监控工具
    memcached可视化客户端工具
    javascript回调函数
  • 原文地址:https://www.cnblogs.com/xiaoyusmile/p/2565963.html
Copyright © 2011-2022 走看看