我想實現一些可重用的對象池。另外,我不想讓API在不需要時將對象放回池中。是否有可能在被調用時阻止垃圾收集?
我想使用垃圾回收器來通知我它將刪除該對象,因爲它沒有引用,所以我可以阻止該對象被垃圾收集並將其放回池中。
我想實現一些可重用的對象池。另外,我不想讓API在不需要時將對象放回池中。是否有可能在被調用時阻止垃圾收集?
我想使用垃圾回收器來通知我它將刪除該對象,因爲它沒有引用,所以我可以阻止該對象被垃圾收集並將其放回池中。
爲什麼不只是保留對象的引用,以便它不會被標記爲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;
如果您的池類只是你想擁有它的對象的名單,他們將永遠不會被垃圾收集,因爲你總是有對池中對象的引用。
但是如何知道對象是否在使用? – 2009-09-24 12:43:03
你會發現這是相對不切實際的。 GC無法通知您將要銷燬的對象。這聽起來像是你正試圖管理你自己的內存空間,這不是C#面向的任務。
不可否認,您可以通過使用池系統和引用計數來完成,以便您知道何時您的對象不被任何人引用。看起來很危險,但。
我不認爲有自己保持引用計數的現實方式。 – 2009-09-24 12:52:08
我認爲理論上可以使用C#弱引用來實現一個回收方案。
這個想法是爲您的託管對象構建代理,並在客戶端請求池中的對象時發出這些代理。該池對實際對象和對代理對象的弱引用持有強烈的參考。 (並且代理對實際對象有很強的參考。)
當應用程序放棄對代理對象的引用時,它將(最終)被垃圾收集,並且(甚至更晚)池中的弱引用將破碎。再後來,池注意到弱引用持有null,然後可以安全地發出新代理,爲其創建新的弱引用並將其發佈給應用程序。
實際上,這真是個壞主意。首先,弱引用對於GC來說可能是昂貴的,並且可能需要多個GC週期來破壞弱引用。並添加池和代理使用的空間,以及通過代理進行操作的性能成本。最有可能的是,這些成本的總和將大大超過使用對象池回收對象的好處。
我不認爲你會得到一個令人滿意的答案,這個池會神奇地返回未使用的對象,否則每個人都會這樣做。 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);
}
}
}
我真的不明白你的意思與清理是有保證的。如果你的意思是把對象返回到池中,那麼肯定的是,然而沒有理由說爲什麼對象不會被引用到外部。 – 2009-09-24 13:56:25
是的,我的意思是它回到了游泳池。我沒有想到就把這句話說完了。 API的合同必須是你應該只使用委託中提供的對象 - 如果你保留了它,那麼行爲將是不確定的,因此它可能不適合某些用途。這可能是大多數API明確釋放的原因:) – Nick 2009-09-24 13:59:39
但是那麼池如何知道對象是否在使用? – 2009-09-24 12:44:03
該對象被引用,而不是「正在使用」。如果它不再被引用,可以用gc代替 – 2009-09-24 12:44:52
您錯過了我的觀點。對象池是跟蹤應用程序未使用的對象的機制,然後根據請求遞交它們。如果池無法告訴應用程序不再使用給定的對象,則無法再安全地將其交出。 – 2009-09-24 12:54:48