代码之家  ›  专栏  ›  技术社区  ›  SqlRyan

定期迭代不断变化的集合

  •  3
  • SqlRyan  · 技术社区  · 14 年前

    我有一个不断变化的对象集合,我想经常显示一些关于内容的信息(我的应用程序是多线程的,不同的线程不断提交修改集合中对象的请求,因此它是不可预测的)。

    如果我锁定集合,我可以迭代它并获得我的信息,而不会出现任何问题—但是,这会导致其他线程出现问题,因为它们可能同时提交了多个修改集合的请求,并且将被暂停。我想了很多办法来解决这个问题,我正在寻求建议。

    • 制作集合的副本并对其进行迭代,从而允许原始集合在后台继续更新。收藏品可能会越来越大,所以这并不理想,但它是安全的。
    • 使用for…next循环对其进行迭代,如果在迭代过程中从集合中移除了项,则捕获indexAutofBounds异常。这可能偶尔会导致重复出现在我的快照中,因此也不是理想的情况。

    还有其他想法吗?我只关心时间快照,所以我不关心反映应用程序中的更改-我主要关心的是集合能够以最小的延迟进行更新,而且更新永远不会丢失。

    3 回复  |  直到 14 年前
        1
  •  2
  •   Strelok    14 年前

    您可能希望研究使用 System.Concurrent 命名空间,如果您使用的是.NETFramework4。例如,从 ConcurrentQueue<T> 类表示A 及时 集合的视图,不受集合更改的影响。 正常的 基础集合中的更改将使集合迭代器无效。否则,您别无选择,只能先锁定集合。可能有并发集合的第三方实现。但我没有调查过。以下是有关.NETFramework4中线程安全集合的信息。

    http://msdn.microsoft.com/en-us/library/dd997305(v=VS.100).aspx

        2
  •  1
  •   Adam Ruth    14 年前

    我倾向于使用您的第一个选项,使用.toArray()创建一个数组,并对其进行迭代。你有没有分析一下它的复制速度有多慢?这对我来说通常是微不足道的,即使是大的收藏。

        3
  •  0
  •   Oak    14 年前

    制作集合的副本通常需要首先锁定集合,因此与仅锁定集合并在其上迭代相比没有任何好处—除非您的集合支持某种快速克隆。

    我认为另一种选择是使用不同类型的集合,那些对并发访问有更好支持的集合,或者能够快速返回快照。这里的另一个答案与.NET特定的答案相关;如果您有兴趣自己实现一个答案,我建议您撰写这篇论文:

    http://www.cs.tau.ac.il/~shanir/concurrent-data-structures.pdf