程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> c#內存管理.(8)

c#內存管理.(8)

編輯:關於C語言

接下來讓我們從垃圾回收器的角度來看一下內存管理。如果我們想清理一下沒用的東西我們可能需要計劃一下怎麼做才更有效率。很明顯,我們需要先區分什麼是垃圾,什麼不是垃圾。那麼我們要先做一個假設:任何東西如果沒有用了那麼就認為是垃圾。幸好我們身邊有兩位好朋友:即時編譯器(JIT)和統一語言運行時(CLR)。JIT和CLR保持著一個列表關於它們正在使用的對象。我們將使用這個列表作為起始列表。我們將保持關於所有正在使用的對象到一個圖表中。所有的活動的對象都將被添加到這個圖表裡。

這也是垃圾回收器所作的事情,從即時編譯器和統一語言運行時那裡得到一份關於所有根對象的引用列表。然後遞歸的查找活動對象的引用去建立一個圖表。

根的組成如下:

l 全局/靜態指針。一種方法確定我們的對象不會被垃圾回收通過保持他們的引用在一個靜態變量裡。

l 棧內指針。我們不想拋棄那些我們應用程序需要使用的東西。

l CPU寄存器指針。在托管堆裡的任何被CPU寄存器的內存地址指向的對象都應該保留。

在上圖當中,對象1和5都被roots直接引用,而對象3則在遞歸搜索中被發現被1引用。如果我們進行類比,那麼對象1是可以看成遙控器,而對象3被看成遠端的設備。當所有對象都進入圖表中後,我們就進行下一步分析。

調整堆

現在我們已經將我們的要保留的對象加到圖表中,現在我們可以分析一下這些東西。

由於對象2是不需要的,所以就像垃圾回收器那樣,我們下移對象3並修改對象1的指針。

然後我們在將對象5下移。

現在我們已經將托管堆進行了緊縮調整,為新來的對象騰出空間。

知道垃圾回收器的工作原理就知道移動對象的工作是很繁重的。從這裡看出如果我們減少移動對象的大小就能提高垃圾回收器的工作效率,因為減少了拷貝內容。

托管堆之外

有時候垃圾回收器需要執行代碼去清理非托管的資源諸如文件,數據庫連接,網絡連接等等。一種有效的控制這些內容的方式是終結器(finalizer)。

class Sample {
  ~Sample () {
    // FINALIZER: CLEAN UP HERE
  }
}

當對象在創建的時候,所有對象附帶的終結器(finalizer)都會添加到終結隊列裡。我們可以說圖中的對象1,4,5擁有終結器(finalizer)並都處於終結隊列中。讓我們看一下當對象2和4在沒有被應用程序引用並且垃圾回收器准備好的情況下會發生什麼。

圖裡對象2被作為無用對象處理。但是,當我們處理對象4的時候,垃圾回收器會先查看它的終結隊列並重新聲明對象4所擁有的內存,對象4被移動並且它的終結器(finalizer)被添加到一個特殊的隊列- freachable。

這裡有專門的線程去處理freachable隊列的成員。一旦對象4的終結器被線程執行,那麼它就會從freachable隊列中移除。然後對象4就可以被回收了。

而對象4在下一次回收開始前仍然存在。

在創建對象時添加終結器(finalizer)是垃圾回收器的一個額外工作。它要花費很高的代價並且嚴重影響垃圾回收器和我們的應用程序的性能。所以請確定在絕對必要的情況下再使用終結器(finalizer)。

有更好的方案用作清理非托管資源。就像你想的那樣,我們可以使用IDisposable接口取代終結器(finalizer)去關閉數據庫鏈接並清理資源。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved