程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 當弱引用對象成為集合元素時(1)

當弱引用對象成為集合元素時(1)

編輯:關於C語言

當我們在系統用到某些占用內存較多的大對象,且該對象並不會被頻繁使用(例如緩存場景)時,若考慮性能因素,或許我們可以選擇使用弱引用(WeakReference)對象。弱引用對象就像是對象之中的“無間行者”,行走於“活動”與“非活動”狀態之間。即使該對象存在引用,垃圾回收器仍然可以對其進行回收,這使得我們對該對象的調用始終存在一種不可預知性,除非我們通過Target屬性賦給對象,以創建強引用,否則我們始終處於這種憂慮之中。這讓我們常常感到左右為難,但在一些追求性能的場景下,使用弱引用未嘗不是明智的選擇。只要我們遵循一定的原則,例如在每次調用弱引用對象時,首先判斷其是否為null,就不會存在太大的問題(如果考慮並發,則需要lock,通常需要做兩次對null的判斷,就如在Singleton模式中對並發支持的實現一樣)。然而,當我們在一個集合對象中存儲弱引用對象時,問題就出現了意想不到的變化。

首先是對集合Count屬性的判斷。如果一個集合對象在某個時刻存儲了10個弱引用對象,當我們調用該集合的Count屬性時,返回的值應該是多少?很顯然,我們不能做預先的判斷。事實上,因為弱引用對象的存在,一個本身線程安全的調用卻出現了並發問題。因為在調用Count屬性期間,GC正有可能回收集合中的某些元素對象。

其次是對迭代器的支持。我們知道,在對IEnumerable進行Foreach遍歷時,不允許我們Add或Remove集合的元素,否則遍歷就會失敗。如果沒有弱引用對象,一切都是美好的。但在我們遍歷存儲了弱引用對象的集合時,GC就會像幽靈一般,不知什麼時候鑽出來搗亂,改變集合元素的個數。很顯然,這樣的集合對迭代器的支持是不安全的。

實質上,這兩個問題的本源是相同的,起因就是弱引用的特殊性。如何解決這個問題?一個簡單辦法是定義自己的弱引用集合,對集合對象進行一個簡單的Wrapper,同時隱藏Count屬性,以及其對IEnumerable的支持。例如,定義一個弱引用列表:

public sealed class WeakReferenceList<T>
{
    private List<WeakReference> m_list;

    public void Add(T object)
    {
        //這裡使用短弱引用,一般不建議使用長弱引用;
        m_list.Add(new WeakReference(object));
    }
    //其它成員
}

WeakReferenceList類並沒有提供GetEnumerator()方法的必要,原因如前所述。至於Count屬性,我們是否可以通過查詢條件,以過濾那些值為null的對象呢?例如:

public int Count
{
    get
    {
        return m_list.Count(e => e.IsAlive);
    }
}

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