垃圾回收器算法之引用計數器法

垃圾回收器算法之引用計數器法

 

         微軟將運行在公共語言運行時裏的代碼成爲託管代碼;但是從更廣泛的意義上來說,只要語言提供了自動內存管理功能,我們使用其開發的代碼都可以稱爲託管代碼;自動內存管理即我們平時所說的垃圾回收器,垃圾回收器的實現是一個複雜的過程,其中涉及到很多的細節;垃圾回收器的難點並不是垃圾的回收過程,而是定位垃圾對象。當一個對象不再被引用的時候就可以被回收了,但是我們怎樣才能知道其沒有被引用呢?

         算法定義

         爲每個對象增加一個字段記錄被引用的次數,並由運行時跟蹤和更新引用的總數;

         object p = new ComparableInt32(57);

object q = p;

我們實例化了一個對象ComparableInt32,並將其賦值給變量p,此時p引用了該對象,所以其計數器爲1;然後我們又用p給變量q賦值,此時q也引用了該變量,所以其計數器變爲2;如下圖所示


從上圖我們可以看到,引用類型每次賦值都需要運行時更新計數器,運行時的更新代碼可能如下

if (p != q)

{

         if (p != null)

                   --p.refCount;

         p = q;

         if (p != null)

                   ++p.refCount;

}

 

計數器算法的一大優勢就是不用等待內存不夠用的時候,才進行垃圾的回收,其可以在賦值操作的同時,檢查計數器是否爲0,如果是的話就可以立即回收;運行時的代碼可能如下

if (p != q)

{

         if (p != null)

                   if (--p.refCount == 0)

                            heap.Release(p);

         p = q;

         if (p != null)

                   ++p.refCount;

}

計數器算法的一大缺點就是不能解決循環引用的問題;如下圖,我們構造了一個列表,我們將最後一個元素的next屬性指向第一個元素,即引用第一個元素,從而構成循環引用;這個時候如果我們將列表的頭head賦值爲null,此時列表的各個元素的計數器都不爲0,同時我們也失去了對列表的引用控制,從而導致列表元素不能被回收!

算法特點

1.       需要單獨的字段存儲計數器,增加了存儲空間的開銷;

2.       每次賦值都需要更新計數器,增加了時間開銷;

3.       垃圾對象便於辨識,只要計數器爲0,就可作爲垃圾回收;

4.       及時回收垃圾,沒有延遲性;

5.       不能解決循環引用的問題;

發佈了110 篇原創文章 · 獲贊 35 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章