在并行处理循环中使用单线程对象的列表



假设我在一个并行处理循环中处理1000个项目
处理一个项目有时需要一个具有专门算法的Calculation对象,该对象需要是单线程的,并且创建成本有些高。

我正在考虑创建一个带有List<Calculation>的容器类,可以要求它在空闲时提供一个这样的对象,或者创建一个新的Calculation对象。

容器类内部的管理必须手动编码,并且必须能够防止不同线程中的错误,所以我认为可能存在一些容易被忽视的故障。

你知道这个场景有C#模式或类型吗?

这被称为对象池。如果创建或销毁对象的成本很高并且有重用的机会,那么它是有用的。

您可以手动操作池。需要时取下物品,用完后归还。这很容易出现错误。您可能会忘记返回项(将它们留给GC,可能会占用文件句柄等资源(。您也可以提前返回,这将导致池的两个使用者同时对同一对象进行操作。

您还可以使用对象复活来确定项目何时被丢弃,并自动将其拉入池中。在我看来,这在实践中是行不通的。根据GC的行为,这可能会导致资源消耗的巨大波动。也有很多潜在的非常糟糕的错误。

很可能您只需要正确使用对象池。类似的模式

var obj = pool.Take();
try {
Use(obj);
}
finally {
pool.Return(obj);
}

脑海中浮现。您也可以为此使用using

我已经通过使用ConcurrentBag集合而不是列表成功地实现了这种线程池。它是线程安全的。类似这样的东西:

ConcurrentBag<Calculation> idle = new ConcurrentBag<Calculation>();
Calculation calc;
if ( idle.IsEmpty || !idle.TryTake(calc)) {
calc = new Calculation();
}
/* start the Calculation object */
/* when it completes toss it in the bag for reuse ... */
idle.Add (calc);

一个袋子就像一张单子,但却是无序的。这对你想做的事情来说很好。

最新更新