.net 循環引用是否會造成內存泄漏


一直想做這么一個測試,人和手的測試。類型"人"有一個屬性"手",需要"手"也可以讀取"人"的數據。則"手"下面也有一個屬性"人"。

如果用代碼表現,則是:

public class Class人
{
    private Class手 _手;
    public Class手 手 { get { return _手; } set { _手 = value; } }

    private Class腳 _腳;
    public Class腳 腳 { get { return _腳; } set { _腳 = value; } }

    private Class腦 _腦;
    public Class腦 腦 { get { return _腦; } set { _腦 = value; } }

    public Class人()
    {
        _手 = new Class手(this);
        _腳 = new Class腳(this);
        _腦 = new Class腦(this);
    }
}

public class Class手
{
    private Class人 _人;
    public Class人 人 { get { return _人; } }

    public Class手(Class人 one)
    {
        _人 = one;
    }
}

這樣可以實現 人.手 和 手.人 的相互訪問。

我的疑問是:人和手之間的這種相互強引用會不會造成資源一直處於被引用狀態,不能被回收,從而導致內存泄漏?

於是做了一個測試,測試的思路是:建立兩個相互引用的類A/B,其中A含有B,B只需要訪問A。A構造的時候會占用大量的內存。執行的時候,在函數以外定義變量C來承裝List<A>並初始化。在函數內,重復的生成A的實例並放到C中。在某個時段,將C清空,強制垃圾回收,看A的集合占用的內存是否會釋放。代碼如下:

public class Class人
{
    private Class手 _手;
    public Class手 手 { get { return _手; } set { _手 = value; } }
public List<string> Data;
    public Class人()
    {
        _手 = new Class手(this);
        Data = new List<string>();
        for (int i = 0; i < 1000; i++)
            Data.Add(Enumerable.Range(1, 30).Select(x => x.ToString()).Aggregate((x, y) => x + y));
    }
}

public class Class手
{
    private Class人 _人;
    public Class人 人 { get { return _人; } }

    public Class手(Class人 one)
    {
        _人 = one;
    }
}

執行代碼:

static List<Class人> data = new List<Class人>();
static void Main(string[] args)
{
    for (int i = 0; i < 1000; i++)
        data.Add(new Class人());

    Console.WriteLine("ok");
    var read = Console.ReadLine();
    if (read == "Y")
    {
        data.Clear();
        GC.Collect();
    }

    Console.ReadKey();
}

測試的結果如下:

1. 在啟動程序前,內存占用61%;

2. 啟動后,"ok"前,也就是生成Class人的實例集合后,內存占用68%。

3.1 如果此時輸入"Y",立刻清空承載的data變量,並進行垃圾回收,內存占用返回至62%,關閉程序后返回61%。

3.2  如果此時輸入"Y",只是清空data,不執行垃圾回收,內存還停留在68%,關閉程序后直接返回61%(參考3.1,等到下一個垃圾回收時,應該會清空至62%)

由此可以推出,即使數據里面,class人和class手相互引用了,但沒有其他數據調用時,垃圾回收機制仍然會將其視為垃圾然后回收。

本來想通過弱引用處理這種相互引用的,通過測試后,感覺不用。以下貼出我查詢到的一些聲音:

".NET不是使用引用計數器的方法"

".NET處理循環引用不是通過弱引用來實現的,而是通過遍歷對象,釋放無法訪問的對象來完成的"

 

由於對.net的垃圾回收機制研究得不通透,所以給不了一些原理上的解釋,如果有大牛知道這一部分,歡迎給我留言。

如果測試結果有誤,請嚴肅糾正。

轉載請注明出處:http://www.cnblogs.com/icyJ


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM