2009-09-24 97 views
1

我想實現一些可重用的對象池。另外,我不想讓API在不需要時將對象放回池中。是否有可能在被調用時阻止垃圾收集?

我想使用垃圾回收器來通知我它將刪除該對象,因爲它沒有引用,所以我可以阻止該對象被垃圾收集並將其放回池中。

回答

0

爲什麼不只是保留對象的引用,以便它不會被標記爲gc?

在回答你的問題在GC如何知道它是不再使用:垃圾回收的

一種方法是保持一個引用計數。當引用計數達到0時,對象不再被引用,並且可以被垃圾收集。 但是,這不是.NET實現它的方式(請參閱Garbage Collection),但它可能有助於理解原理。

編輯: 我怎麼理解它,你需要一個曾經被實例化過的對象池,並且你可以分配和收集。基本上你想在GC之上實現內存管理。

我希望做到這一點的唯一原因是創建對象的新實例並使其可用(初始化)需要太多時間。

在任何情況下,你可以試試傳統的非託管方法:

Stack pool = new Stack(); 

// Initialize a few MyObjects 
pool.Push(new MyObject()); 


// Get an instance of the object from the pool 
MyObject obj = (MyObject)pool.Pop(); 

// Use the object 
obj.Foo(); 

// When you are finished clean up 
pool.Push(obj); 
obj = null; 
+0

但是那麼池如何知道對象是否在使用? – 2009-09-24 12:44:03

+0

該對象被引用,而不是「正在使用」。如果它不再被引用,可以用gc代替 – 2009-09-24 12:44:52

+0

您錯過了我的觀點。對象池是跟蹤應用程序未使用的對象的機制,然後根據請求遞交它們。如果池無法告訴應用程序不再使用給定的對象,則無法再安全地將其交出。 – 2009-09-24 12:54:48

0

如果您的池類只是你想擁有它的對象的名單,他們將永遠不會被垃圾收集,因爲你總是有對池中對象的引用。

+0

但是如何知道對象是否在使用? – 2009-09-24 12:43:03

0

你會發現這是相對不切實際的。 GC無法通知您將要銷燬的對象。這聽起來像是你正試圖管理你自己的內存空間,這不是C#面向的任務。

不可否認,您可以通過使用池系統和引用計數來完成,以便您知道何時您的對象不被任何人引用。看起來很危險,但。

+0

我不認爲有自己保持引用計數的現實方式。 – 2009-09-24 12:52:08

0

我認爲理論上可以使用C#弱引用來實現一個回收方案。

這個想法是爲您的託管對象構建代理,並在客戶端請求池中的對象時發出這些代理。該池對實際對象和對代理對象的弱引用持有強烈的參考。 (並且代理對實際對象有很強的參考。)

當應用程序放棄對代理對象的引用時,它將(最終)被垃圾收集,並且(甚至更晚)池中的弱引用將破碎。再後來,池注意到弱引用持有null,然後可以安全地發出新代理,爲其創建新的弱引用並將其發佈給應用程序。

實際上,這真是個壞主意。首先,弱引用對於GC來說可能是昂貴的,並且可能需要多個GC週期來破壞弱引用。並添加池和代理使用的空間,以及通過代理進行操作的性能成本。最有可能的是,這些成本的總和將大大超過使用對象池回收對象的好處。

1

我不認爲你會得到一個令人滿意的答案,這個池會神奇地返回未使用的對象,否則每個人都會這樣做。 Java有一個ReferenceQueue,垃圾收集對象被放置在該ReferenceQueue上,但即使在那裏,我也不會建議,這取決於GC的行爲。

如果你想避免必須顯式釋放池中的對象,你有沒有想過使用回調/委託函數? API將接受將提供對象的委託,並且應用程序可以使用委託中的對象。完成後,保證清理。 (編輯:我的意思是保證返回到游泳池)。

class Pool 
{ 
    public delegate void UseResource(Object object); 
    public void GetObject(UseResource del) 
    { 
    Object o = null; 
    try { 
     o = getFromPool(); 
     del(o) 
    } finally { 
     if (o != null) returnToPool(o); 
    } 
    } 
} 
+1

我真的不明白你的意思與清理是有保證的。如果你的意思是把對象返回到池中,那麼肯定的是,然而沒有理由說爲什麼對象不會被引用到外部。 – 2009-09-24 13:56:25

+0

是的,我的意思是它回到了游泳池。我沒有想到就把這句話說完了。 API的合同必須是你應該只使用委託中提供的對象 - 如果你保留了它,那麼行爲將是不確定的,因此它可能不適合某些用途。這可能是大多數API明確釋放的原因:) – Nick 2009-09-24 13:59:39