自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

.NET垃圾收集關(guān)鍵方法解析

開發(fā) 后端
文章通過分析.NET垃圾收集中的重要方法,讓大家更加了解.Net GC的運(yùn)行機(jī)制,相信大家通過本文,能夠很全面的了解.NET GC方面的知識(shí)。

之前51cto曾報(bào)道過關(guān)于.NET垃圾收集機(jī)制中的算法與代齡,說到.NET垃圾收集,就不得不提到其中的關(guān)鍵方法,其是實(shí)現(xiàn).NET GC運(yùn)行機(jī)制的前提。

1.Dispose()方法

Dispose可用于釋放所有資源,包括托管的和非托管的,需要自己實(shí)現(xiàn)。大多數(shù)的非托管資源都要求手動(dòng)釋放,我們應(yīng)當(dāng)為釋放非托管資源公開一個(gè)方法,實(shí)現(xiàn)釋放非托管資源的方法有很多種,實(shí)現(xiàn)IDispose接口的Dispose方法是***的,這可以給使用你類庫的程序員以明確的說明,讓他們知道怎樣釋放你的資源;而且C#中用到的using語句快,也是在離開語句塊時(shí)自動(dòng)調(diào)用Dispose方法。

這里需要注意的是,如果基類實(shí)現(xiàn)了IDispose接口,那么它的派生類也必須實(shí)現(xiàn)自己的IDispose,并在其Dispose方法中調(diào)用基類中Dispose方法。只有這樣的才能保證當(dāng)你使用派生類實(shí)例后,釋放資源時(shí),連同基類中的非托管資源一起釋放掉。

使用using與try+finally的區(qū)別

可以說二者沒有任何區(qū)別,因?yàn)閡sing只是編輯器級(jí)的優(yōu)化,它與try+finally有著相同的作用,以下是一段使用using的代碼,它在IL階段也是以try+finally呈現(xiàn)的,但是,using的優(yōu)點(diǎn)是,在代碼離開using塊時(shí),using會(huì)自動(dòng)調(diào)用Idispose接口的Dispose()方法。

  1. public partial class _Default : System.Web.UI.Page  
  2. {      
  3. protected void Page_Load(object sender, EventArgs e)   
  4. {   
  5. using (DataSet ds = new DataSet())  
  6. {   
  7.  }  
  8. }  
  1. .method family hidebysig instance void  Page_Load(object sender,class [mscorlib]System.EventArgs e) cil managed  
  2. {  
  3.     // 代碼大小       29 (0x1d)  
  4.     .maxstack  2  
  5.     .locals init ([0] class [System.Data]System.Data.DataSet ds,  
  6.              [1] bool CS$4$0000)  
  7.     IL_0000:  nop  
  8.     IL_0001:  newobj     instance void [System.Data]System.Data.DataSet::.ctor()  
  9.     IL_0006:  stloc.0  
  10.     .try  
  11.     {  
  12.       IL_0007:  nop  
  13.       IL_0008:  nop  
  14.       IL_0009:  leave.s    IL_001b  
  15.     }  // end .try  
  16.     finally  
  17.     {  
  18.       IL_000b:  ldloc.0  
  19.       IL_000c:  ldnull  
  20.       IL_000d:  ceq  
  21.       IL_000f:  stloc.1  
  22.       IL_0010:  ldloc.1  
  23.       IL_0011:  brtrue.s   IL_001a  
  24.       IL_0013:  ldloc.0  
  25.       IL_0014:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()  
  26.       IL_0019:  nop  
  27.       IL_001a:  endfinally  
  28.     }  // end handler  
  29.     IL_001b:  nop  
  30.     IL_001c:  ret  
  31. } // end of method _Default::Page_Load 

2. GC.Collect()方法

如果我們在程序中顯式的調(diào)用了垃圾收集器的collect接口,那么垃圾收集器會(huì)立即運(yùn)行,完成內(nèi)存對象的標(biāo)記、壓縮與清除工作,使用GC.Collect(i)還可以指定回收的代,然而aicken并不贊成各位同學(xué)顯式調(diào)用它:

(1)GC.Collect()做的并不只是回收內(nèi)存,就像***節(jié)中介紹的,在回收了內(nèi)存之后,GC會(huì)重新整理內(nèi)存,修正對象指針,讓空閑內(nèi)存連續(xù),供CLR順序分配內(nèi)存,提高新建對象的效率。內(nèi)存壓縮整理工作非常耗用計(jì)算資源。

(2)很少有人會(huì)關(guān)心到GC除了在內(nèi)存吃緊以及資源空閑時(shí)運(yùn)行,還會(huì)在什么時(shí)候運(yùn)行。 其實(shí)GC的運(yùn)行時(shí)機(jī),還要受到一個(gè)叫做“策略引擎”的部件控制,它會(huì)觀察GC的收集頻率、效率等等。它會(huì)根據(jù)GC回收效果,調(diào)整GC運(yùn)行的頻率:即當(dāng)某次GC回收效果頗豐時(shí),它便會(huì)增加GC運(yùn)行的頻率,反之亦然。

所以如果剛剛發(fā)生了一次自然的收集,垃圾對象就會(huì)非常之少,而此時(shí)程序又顯式的進(jìn)行了收集調(diào)用,那么自然, GC雖然小有收獲,但是策略引擎就會(huì)認(rèn)為:這很不值得,才收集了這么點(diǎn)垃圾,也許該減少GC的次數(shù)。這樣一來,垃圾收集器努力保持的自然節(jié)奏就被打亂了,同時(shí),對象類型的創(chuàng)建效率與頻率,也會(huì)被“策略引擎”捕捉到,從而改變代的數(shù)量與容量。

所以,額外的調(diào)用GC,代價(jià)高昂,甚至?xí)档托省o@示的調(diào)用GC.Collect(),實(shí)質(zhì)是在用“時(shí)間換空間”,而通常在程序設(shè)計(jì)中,我們推薦的設(shè)計(jì)原則是“空間換時(shí)間”,比如使用各種各樣的緩存,也有例外,如果你掌握了整個(gè)應(yīng)用程序的情況,明確的知道何時(shí)會(huì)產(chǎn)生大量垃圾,也是可以顯示調(diào)用該方法的。綜上,盡量不要顯示調(diào)用GC.Collect(),因?yàn)榉?wù)器的CPU比內(nèi)存要貴的多! #p#

3. 析構(gòu)函數(shù)(Finalize())

我們知道,GC只負(fù)責(zé)釋放托管資源,非托管資源GC是無法釋放的。類似文件操作、數(shù)據(jù)庫連接等都會(huì)產(chǎn)用非托管資源。Finalize方法是用于釋放非托管資源的,等同于C#中是析構(gòu)函數(shù),C#編譯器在編譯構(gòu)造函數(shù)時(shí),會(huì)隱式的將析構(gòu)函數(shù)編譯為Finalize()對應(yīng)的代碼,并確定在finally塊中執(zhí)行了base.Finalize()。析構(gòu)函數(shù)中只能釋放非托管資源,而不要在任何托管資源進(jìn)行析構(gòu),原因如下:

(1)你無法預(yù)測析構(gòu)函數(shù)的運(yùn)行時(shí)機(jī),它不是按順序執(zhí)行的。當(dāng)析構(gòu)函數(shù)被執(zhí)行的時(shí)候,也許你進(jìn)行操作的托管資源已經(jīng)被釋放了。

(2)包含F(xiàn)inalize()的對象,需要GC的兩次處理才能刪除。

(3)CLR會(huì)在單獨(dú)的線程上執(zhí)行所有對象的Finalize()方法,無疑,如果頻繁的Finalize(),會(huì)降低系統(tǒng)的性能。

下面我們來重點(diǎn)說說第(2)點(diǎn),為何包含F(xiàn)inalize()的對象,需要兩次GC才能被清除。首先要了解與Finalize相關(guān)的兩個(gè)隊(duì)列:終止隊(duì)列(Finalization Queue)與可達(dá)隊(duì)列(Freachable Queue),這兩個(gè)隊(duì)列存儲(chǔ)了一組指向?qū)ο蟮闹羔?,?dāng)程序中在托管堆上分配空間時(shí)(new),如果該類含有析構(gòu)函數(shù),GC將在Finalization Queue中添加一個(gè)指向該對象的指針。

在GC***運(yùn)行時(shí),會(huì)在已經(jīng)被確認(rèn)為垃圾的對象中遍歷,如果某個(gè)垃圾對象的指針被Finalization Queue包含,GC將這個(gè)對象從垃圾中分離出來,將它的指針儲(chǔ)存到Freachable Queue中,并在Finalization Queue刪除這個(gè)對象的指針記錄,這時(shí)該對象就不是垃圾了——這個(gè)過程被稱為是對象的復(fù)生(Resurrection)。當(dāng)Freachable Queue一旦被添加了指針之后,它就會(huì)去執(zhí)行對象的Finalize()方法,清除對象占用的資源。

當(dāng)GC再次運(yùn)行時(shí),便會(huì)再次發(fā)現(xiàn)這個(gè)含有Finalize()方法的垃圾對象,但此時(shí)它在Finalization Queue中已經(jīng)沒有記錄了(GC***運(yùn)行時(shí)刪掉了它的Finalization Queue記錄),那么這個(gè)對象就會(huì)被回收了,至此,通過GC兩次運(yùn)行,終于回收了帶有析構(gòu)函數(shù)的對象。復(fù)活實(shí)例:

  1. private void Form1_Load(object sender, EventArgs e)   
  2. {  
  3. Resource re = new Resource();     
  4. re = null;GC.Collect();  
  5. GC.WaitForPendingFinalizers();  
  6. //***GC.Collect()沒起作用哦。   
  7. label1.Text = re.num.ToString();  
  8. }    
  9. public class Resource  
  10. {  
  11. public int num;  
  12. ~Resource()  
  13. {  
  14.  
  15. }  
  16. }  

看了上面的代碼,大家應(yīng)該了解什么是復(fù)活了吧!那么為什么要復(fù)生呢?因?yàn)?**GC時(shí),這個(gè)對象的Finalize()方法還沒有被執(zhí)行,如果不經(jīng)過復(fù)生就被GC掉,那么就連它的Finalize()一起回收了,F(xiàn)inalize()就無法運(yùn)行了,所以必須先復(fù)生,以執(zhí)行它的Finalize(),然后再回收。

還有兩個(gè)方法ReRegisterForFinalize和SuppressFinalize需要講一講,ReRegisterForFinalize是將指向?qū)ο蟮闹羔樦匦绿砑拥紽inalization Queue中(即召喚系統(tǒng)執(zhí)行Finalize()方法),SuppressFinalize是將對象的指針從Finalization Queue中移除(即拒絕系統(tǒng)執(zhí)行Finalize()方法)。

SuppressFinalize用于那些即有析構(gòu)函數(shù)來釋放資源,又實(shí)現(xiàn)了Dispose()方法釋放資源的情況下:將GC.SuppressFinalize(this)添加至Dispose()方法中,以確保程序員調(diào)用Dispose()后,GC就不必再次收集了,即實(shí)現(xiàn)Idisposable中的Dispose()方法,又使用析構(gòu)函數(shù),一個(gè)雙保險(xiǎn),大家不要迷惑,其實(shí)在釋放非托管資源時(shí),使用一個(gè)即可,推薦使用前者。代碼如下:

  1. public class Resource : Idisposable  
  2. {  
  3.   private bool isDispose = false;  
  4.   //實(shí)現(xiàn)Dispose(),后面還有析構(gòu)函數(shù),以防程序員忘記調(diào)用Dispose()方法  
  5.     public void Dispose()   
  6.       {  
  7.        Dispose(true);  
  8.     GC.SuppressFinalize(this);  
  9.       }  
  10.    protected virtual void Dispose(bool disposing)  
  11.    {  
  12.     if (!isDispose)  
  13.     {  
  14.      if (disposing)  
  15.      {  
  16.       //清理托管資源  
  17.      }  
  18.      //清理非管資源  
  19.     }  
  20.     isDispose = true;  
  21.    }  
  22.       Resource ()  
  23.    {  
  24.     Dispose(false);  
  25.    }  
  26.  } 

4.弱引用(WeakReference)

***一個(gè)話題:弱引用。在編程中,對于那些大對象建議使用這種引用方式,這種引用不影響GC回收:我們用過了某個(gè)對象,然后將其至null,這樣GC就可以快速回收它了,但是沒過多久我們又需要這個(gè)對象了,沒辦法,只好重新創(chuàng)建實(shí)例,這樣就浪費(fèi)了創(chuàng)建實(shí)例所需的計(jì)算資源;而如果不至null,就會(huì)浪費(fèi)內(nèi)存資源。對于這種情況,我們可以創(chuàng)建一個(gè)這個(gè)大對象的弱引用,這樣在內(nèi)存不夠時(shí)GC可以快速回收,而在沒有被GC回收前我們還可以再次利用該對象。

  1. public class SomeObject   
  2. {  
  3.  
  4. }  
  5. public static void Main()   
  6. {  
  7.  SomeObject so = new SomeObject();  
  8.  WeakReference WRso = new WeakReference(so);  
  9.  so = null;  
  10.  Console.WriteLine(WRso.IsAlive); // True  
  11.  // 調(diào)用GC 手動(dòng)回收。  
  12.  GC.Collect();  
  13.  Console.WriteLine(WRso.IsAlive); // False  

看到?jīng)],在so = null;后,它的弱引用依然是可用的。所以對于大對象的使用,aicken建議使用此種方式。另外,弱引用有長短之分:長弱引用在對象終結(jié)后,依然追蹤對象;短弱引用則反之,aicken不建議人為干預(yù)GC的工作成果,所以推薦使用短弱引用,即上面代碼中的方式。

文章原標(biāo)題:.NET Discovery系列之三--深入理解.NET垃圾收集機(jī)制(下)

原文鏈接:http://www.cnblogs.com/isline/archive/2009/03/04/1402713.html

【編輯推薦】

  1. .NET垃圾收集機(jī)制 了解算法與代齡
  2. 淺析提高.NET垃圾回收性能的幾種方法
  3. 觀點(diǎn):微軟.NET各子技術(shù)領(lǐng)域的應(yīng)用前景
  4. .NET Framework 4.0功能特點(diǎn)詳細(xì)講解
  5. 深入.NET Framework 4.0 關(guān)于Lazy的點(diǎn)滴
責(zé)任編輯:王曉東 來源: CSDN博客
相關(guān)推薦

2010-01-06 16:33:50

.Net Framew

2010-02-22 08:58:35

JVM內(nèi)存模型垃圾收集

2009-10-30 10:47:48

VB.NET垃圾收集器

2010-03-04 10:08:54

.Net垃圾收集

2009-06-15 16:14:40

Java垃圾收集算法GC

2024-03-27 10:27:35

延遲垃圾收集器

2024-01-15 11:12:28

Go內(nèi)存開發(fā)

2024-07-15 08:00:00

2009-09-18 09:16:06

.NET垃圾回收

2021-09-07 11:23:09

智能垃圾箱物聯(lián)網(wǎng)IOT

2010-01-21 16:37:56

VB.NET變量聲明

2011-05-10 16:04:45

Java垃圾收集器

2011-08-17 15:37:23

Objective-C垃圾收集

2010-01-15 16:12:40

VB.NET調(diào)用DLL

2010-01-18 18:06:07

VB.NET多線程

2010-01-21 17:48:25

VB.NET Sing

2024-05-28 00:00:03

Java垃圾收集機(jī)制

2023-02-26 11:50:04

Hbase程序Oracle

2017-05-09 15:34:54

方案垃圾收集信息化

2011-07-21 14:54:26

java垃圾收集器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)