成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

.NET對象清理:垃圾回收和資源清理

原創
開發 后端
在 .NET 中垃圾回收和資源清理是重中之重的內容,也是所有程序都必須用到的機制,但是有很大一部分開發人員并不知道垃圾回收和資源清理的原理。那么,我將通過這篇文章向各位讀者詳細講解一下垃圾回收和資源清理。

[[318251]]

【51CTO.com原創稿件】在 .NET 中垃圾回收和資源清理是重中之重的內容,也是所有程序都必須用到的機制,但是有很大一部分開發人員并不知道垃圾回收和資源清理的原理。那么,我將通過這篇文章向各位讀者詳細講解一下垃圾回收和資源清理。

一、垃圾回收

.NET中垃圾回收是運行時的核心功能,它的作用是回收不再被引用的對象所占用的內存。這里我們要注意垃圾回收器只回收內存資源而不處理其他資源。此外垃圾回收器是根據是否存在任何引用來決定要清理那些東西,也就是說垃圾回收器處理的是不被引用的引用對象,并且只能回收堆上的內存。

  1. 簡述 在 .NET 中垃圾回收的很多細節都和 CLI 有關,我們常用的 Microsoft.NET 框架中實現垃圾回收的算法是 mark-and-compact 算法 。當每次一次垃圾回收周期開始時,它會查找對象的所有根引用(一般來說根引用來自靜態變量、CPU寄存器和局部變量或參數實例的任何引用)。基于查找到的所有根引用,垃圾回收器就可以遍歷每個根引用標識的樹形結構,并遞歸確定每個根引用指向的對象,進而識別出所有可達對象。

    當執行垃圾回收時,垃圾回收器會將所有可達對象一個挨一個的放在一起,這樣就可以覆蓋不可達對象所占用的內存。為了定位和移動可達對象,進程中所有托管線程都會在垃圾回收期間暫停運行,這樣就可以保證垃圾回收器在運行期間維持狀態一致性。雖然這么做會造成應用程序短暫停止工作,但是一般來說只要垃圾回收周期不是特別長,這個短暫的停止工作是很難發覺的。在我們開發時有時可能不希望在運行一些代碼段時執行垃圾回收,這時我們可以在代碼段之前使用 System.GC 對象所包含的 Collect 方法來讓垃圾回收暫時跳過這些代碼。當然這么做是不會阻止垃圾回收運行的,只是減少了這部分代碼可能被回收的概率,但是這里有一個前提條件:代碼段執行期間不會發生內存被大量消耗使用的情況。在 .NET 中垃圾回收有一個特別的地方,就是并非所有的垃圾都會在一個垃圾回收周期內被回收。這是為什么呢?因為在 .NET 垃圾回收器中有一個名字叫 generation 的概念,翻譯成中文就是 。它會清理那些生存時間較短的對象,那些在一次垃圾回收周期中存活下來的對象會降低清理頻率。也就是說當一個對象在一次垃圾回收周期中存活下來,那么它將會被移動到下一代中,如果它又在一次垃圾回收周期中存活下來,那么它將被移動到最后一代,也就是第二代(為什么是第二代呢?因為 .NET 垃圾回收機制中代是從 0 開始的),第零代清理速度最快,第二代清理速度最慢。
  2. 弱引用 弱引用這個名詞很少有開發人員聽過,所謂的弱引用是為創建起來開銷很高并且維護成本也很大的對象而設計的。它不阻止垃圾回收器對對象的回收,但會維持一個引用,進而可以在被垃圾回收器回收之前可以重用。例如我們從數據庫中查詢一個龐大的數據列表向用戶展示,如果沒有使用弱引用當用戶關閉了這個列表,那么垃圾回收器就有很大可能將它回收,那么當用戶再次查看這個列表時,程序又需要從數據庫查詢并加載出來,這種操作成本是很高昂的。如果使用了如引用,每次請求列表時代碼首先檢查列表是否被清除,如果沒有被清除就直接將列表展示給用戶,如果被清除了就從數據庫查詢并展示給用戶,這就相當于對象在內存中進行了緩存。如果開發人員認為對象應該進行弱引用,那么就可以把這個對象賦值給 System.WeakReference 。下面我們來看一個弱認證的簡單例子:

    1. WeakReference Data; 
    2. public FileStream Date() 
    3.    FileStream fs= (FileStream)Data.Target; 
    4.    if(data!=null
    5.   { 
    6.        return data; 
    7.   } 
    8.    // more code 
    9.    Data.Target=data; 
    10.    return data; 

    上面的代碼是一個標準的創建弱引用的代碼,我們可以看到在代碼中對變量 data 進行了 null 判斷,我們可以通過這個判斷來檢查垃圾回收器是否將其回收。這里還有一個關鍵代碼 FileStream fs= (FileStream)Data.Target; 這里將弱引用賦值給了強引用,這樣可以避免在檢查 null 后和訪問數據前,發生垃圾回收器回收弱引用。

二、資源清理

在前面一小節開頭我們說過垃圾回收之回收內存中的對象,那么如果我們需要回收其他資源呢,例如數據庫連接、句柄、外部設備。這時我們就需要用到資源清理。

終結器 終結器是一個允許開發人員通過代碼來清理類資源的東西。終結器最大的特征是它不能在代碼中顯式調用,只有垃圾回收器負責對對象的實例調用終結器,因此開發人員無法在編譯時確定終結器在何時執行,只能夠確定終結器時對象中最后一次被調用的地方。 終結器的定義也很簡單,只需要在類名之前加一個 ~ 符號即可。 

  1. class Demo 
  2.    public Demo(string name
  3.   { 
  4.        //more code 
  5.   } 
  6.     
  7.    ~Demo() 
  8.   { 
  9.        Close(); 
  10.   } 
  11.    public void Close() 
  12.   { 
  13.        //more code 
  14.   } 
  15.    //more code 

上述代碼我們就定義了一個簡單的終結器,我們定義終結器的時候需要注意以下四點:

因為終結器是在自己的線程中執行的,因此如果終結器中存在一個未處理的異常就會很難診斷發現,因為造成異常的情況并不清晰透明。所以我們必須避免在終結器中引發異常。 

  • 終結器是不允許傳遞任何參數的,也不能重載它;
  • 因為它是被垃圾回收器所調用,因此給終結器加上訪問修飾符是毫無意義的;
  • 如果父類中存在終結器,那么將會作為子類終結器的一部分被自動調用;
  • 終結器必須顯示的釋放資源。
  1. using 雖然終結器可以幫助我們在忘記顯式調用必要清理代碼的時候執行清理,但是因為終結器的運行存在不確定性,因此我們只能將它作為備用機制。正常情況下我們可以使用 using C# 中的 IDisposable 接口的 Dispose 方法為我們提供了實現細節。我們先來看一段代碼。

    1. class Demo 
    2.    MyFileStream fs =new myFileStram(); 
    3.    //more code 
    4.    fs.Dispose(); 
    5.    //more code 
    6. class MyFileStream:IDisposable 
    7.    public MyFileStream(string path) 
    8.   { 
    9.        //more code 
    10.   } 
    11.    //more code 
    12.    ~MyFileStream 
    13.   { 
    14.        Dispose(false); 
    15.   } 
    16.    public void Close() 
    17.   { 
    18.        Dispose(); 
    19.   } 
    20.    public void Dispose() 
    21.   { 
    22.        Dispose(true); 
    23.        System.GC.SuppressFinalize(); 
    24.   } 
    25.    public void Dispose(bool para) 
    26.   { 
    27.        // more code 
    28.   } 

    上述代碼中我們顯式調用了 MyFileStream 類的 Dispose 方法。 Dispose 方法主要用來清理已經用過的資源,但是這里存在一個問題,當我們調用 Dispose 方法時有可能會發生異常,這時我們就無法正確調用 Dispose 方法了,為了避免這個問題我們需要加入 try..finally 塊。但是我們無法保證開發人員每次都會寫 try...finally ,這時我們可以使用 C# 提供的 using 語句,我們將上面的調用代碼修改一下:

    1. class Demo 
    2.    using(MyFileStream fs =new myFileStram()) 
    3.   { 
    4.        //more code 
    5.   } 

    這段代碼最終生成的 CIL 代碼和使用 try...finally 塊生成的代碼完全一樣。

  2. 垃圾回收、終結和 IDisposable 在上一小節的代碼中我們看到在 Dispose 方法中我們調用了 System.GC.SuppressFinalize(); ,它的作用是從終結隊列中移除 MyFileStream 實例。因為所有清理都在Dispose 方法中完成了,而不是等著終結器執行。如果不調用 System.GC.SuppressFinalize() 方法實例將會一直在終結隊列中,只有當終結方法被調用之后才能在垃圾回收器中被回收,那么這就造成了托管資源垃圾回收處理時間的延遲。 Dispose 方法中調用了 Dispose(bool para) 方法,在這個方法里我們可以清理資源并阻止終結器。其次,我們定義了 Close 方法來調用 Dispose(bool para) 方法,這樣終結器就可以調用 Dispose(bool para) 方法來關閉釋放資源。針對前一小結的代碼需要有如下幾點注意:

    在某些特殊情況下垃圾回收的對象有可能會被無意中重新引用一個待終結的對象。這樣,被重新引用的對象就不再是不可訪問的,所以不能當作垃圾被回收掉。假如對象的終結方法已經運行,那么除非顯式標記為要進行終結,否則終結方法不一定會再次運行。

  • 只針對開銷大,成本高的對象實現終結器;
  • 如果類存在終結器那么就必須實現 IDisposable ;
  • 不要在終結器中拋出異常;
  • 在 Dispose 方法中必須調用 System.GC.SuppressFinalize ;
  • 保證 Dispose 可以被重用;
  • 保證 Dispose 方法的簡單性;
  • 不能在終結器中調用未被終結的其他對象;
  • 如果父類存在終結器,再重寫時必須調用父類終結器;
  • 調用 Dispose 方法之后,將對象設為不可用。

三、小結

這篇文章詳細講解了垃圾回收和資源清理相關的知識,對于部分開發人員來說這部分知識可能晦澀難懂,但是只要在實際項目中上手使用,我相信就可以很快的掌握和理解。

作者介紹:

朱鋼,筆名喵叔,國內某技術博客認證專家,.NET高級開發工程師,7年一線開發經驗,參與過電子政務系統和AI客服系統的開發,以及互聯網招聘網站的架構設計,目前就職于一家初創公司,從事企業級安全監控系統的開發。

【51CTO原創稿件,合作站點轉載請注明原文作者和出處為51CTO.com】

 

責任編輯:龐桂玉 來源: 51CTO
相關推薦

2012-12-18 13:57:42

.NetC#

2013-08-19 17:25:18

.Net托管

2009-06-15 16:14:40

Java垃圾收集算法GC

2009-02-18 20:35:13

Windows系統垃圾

2022-01-20 10:34:49

JVM垃圾回收算法

2021-09-05 23:50:56

手機內存技術

2021-10-25 22:40:27

Windows 10Windows微軟

2024-07-25 11:22:23

2022-03-21 11:33:11

JVM垃圾回收器垃圾回收算法

2021-11-05 15:23:20

JVM回收算法

2021-12-26 18:23:10

Kubernetes集群命令

2009-08-26 08:52:13

Windows 7垃圾清理

2012-05-02 16:09:13

系統垃圾

2009-08-21 19:10:53

Windows 7系統垃圾清理

2021-12-08 23:19:11

手機蘋果內存

2022-10-08 18:25:22

Python內存管理GC

2017-08-04 10:53:30

回收算法JVM垃圾回收器

2018-04-08 16:49:47

App Store應用程序蘋果

2011-08-29 16:07:35

Ubuntu

2021-01-04 10:08:07

垃圾回收Java虛擬機
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91不卡在线 | 久久视频免费看 | 超碰av在线| 免费黄色的视频 | 97人人澡人人爽91综合色 | 国产精品乱码一区二三区小蝌蚪 | 欧美一区二区大片 | 男人天堂视频在线观看 | 91精品无人区卡一卡二卡三 | 91在线观看视频 | 日韩a视频| 女人牲交视频一级毛片 | 一区二区三区视频在线 | 午夜精品一区二区三区在线观看 | 亚州成人 | 国产精品视频久久久 | 色射综合| 欧美激情久久久 | 国产精品高清在线 | 一区二区三区免费在线观看 | 91久久综合亚洲鲁鲁五月天 | 日本久久视频 | 日韩精品在线看 | 99热热99 | 精品久久久久一区二区国产 | 国内自拍偷拍 | 国产精品视频一二三区 | 久久综合九九 | 国产做a爱片久久毛片 | 久久精品亚洲国产奇米99 | 国产成人精品a视频一区www | 欧美簧片 | 中文字幕一区二区三区四区五区 | 欧美福利一区 | 一区二区三区国产 | 欧美精品1区2区 | 999久久久久久久久6666 | 久久精品中文 | 欧美自拍一区 | 亚洲精品国产电影 | 特级做a爰片毛片免费看108 |