在没有比赛的情况下在ConcurrentMultimap上实现删除

时间:2010-09-28 13:00:53

标签: java concurrency guava multimap concurrenthashmap

我一直在研究编写并发Multimap的问题,我有一个由Google Guava AbstractSetMultimap和MapMaker计算映射支持的实现,它根据需要创建值集合作为在ConcurrentHashMap上设置视图。有些关注视图集和各种包装器,我认为这非常接近。

discussed others have试过这个问题已经the discussion here的大问题,似乎是当底层地图变空时将其删除,没有引入竞争条件。

似乎存在两种选择。

  • 将空集合留在那里。这会泄漏一些CHM,但我认为它至少是正确的。
  • 乐观地尝试在空时删除集合并补偿其中是否还有其他内容。这充满了种族,似乎无法修复。
  • 同步values-collection上的所有内容,这至少允许删除,但是以按键初始查找后的任何并发为代价。
  • 对于较小的惩罚(可能,取决于使用模式?),也许同步值集合的创建和删除,需要检查是否涵盖了所有内容。

问题:

  • 有谁知道比这更好的实施?我们可以更好地组合MapMaker,还是需要从头开始编写专门的ConcurrentHashMultimap?
  • 如果难以在此方面取得很大进展,那么这种泄漏在实践中可能是一个很大的问题吗?诸如java.util.HashMap,juc.ConcurrentHashMap和ArrayDeque等值得注意的集合不会向下调整后备存储的大小,并且ArrayList不会自动执行此操作。只要我们清理掉这些物体,我就想知道这是否会过重。

由于


编辑:另请参阅guava邮件列表中的this Google code area


编辑2:我已经写完了。有关实施,请参阅{{3}}。我非常感谢任何尝试它的人的反馈,而不是在这里。

4 个答案:

答案 0 :(得分:1)

我之前提出了同样的问题,最终实现了4种不同的实现。

问题: High-performance Concurrent MultiMap Java/Scala

impl(我称之为索引) http://github.com/jboner/akka/blob/master/akka-actor/src/main/scala/actor/ActorRegistry.scala#L314

答案 1 :(得分:0)

如果你真的不想泄漏空集合,你可以尝试用每个键占位符Future原子地替换它。这样,并发添加/删除或添加/添加应该能够在再次扩展时达到一致状态。

答案 2 :(得分:0)

使用不可变集合作为值是解决/简化基本并发问题的最佳方法,然后可以使用原子替换方法进行删除。不幸的是,通常使用的快速复制/更新配置文件不具有不可变集合,因此您通常需要进行相当昂贵的复制。

答案 3 :(得分:0)

作为后续内容,以下是我之前讨论中遗漏的一些细节,这些讨论是关于我的并发多图实现的。

该实现遵循了您的第一个建议:在支持映射中留下空集合。以下实时视图行为会使您的其他建议变得复杂。

Multimap<String, Integer> multimap = HashMultimap.create();
Set<Integer> set = multimap.get("foo");
multimap.put("foo", 1);
int count = set.size();   // equals 1

对于真实世界的应用程序而言,与集合库类相反,少于完全并发的多重映射的东西可能就足够了。您可以定义自己的类,该类实现Multimap接口的子集或有限的并发保证选择。或者,您的应用程序逻辑可以最小化同步多图的争用,以避免性能问题。