【问题标题】:Do I need a concurrent hash map if each thread inserts unique keys?如果每个线程都插入唯一键,我是否需要并发哈希映射?
【发布时间】:2012-11-21 14:04:20
【问题描述】:

据我了解,从 Java 5 开始的并发哈希映射为您提供了一个线程安全的哈希映射,它不使用阻塞访问进行迭代器和更新(如果并发级别足够的话)。

鉴于以下条件:

  1. 插入只发生一次(在应用程序初始化期间)。
  2. 每个线程都有一组要插入的键,这些键不被任何其他线程共享。
  3. 永远不会更新。
  4. 只有在应用程序初始化结束后才会进行选择。

使用简单的哈希映射会更好吗?

我的理解是我可能会过得更好,因为我的钥匙不会发生冲突——我可以保证。但是,Java 实现是否有可能通过将同一个桶分配给两个不同的键来搞砸哈希桶?

【问题讨论】:

  • 如果有疑问,为什么不直接使用ConcurrentHashMap
  • @MonsterTruck:如果这只是在启动时,争用对你的伤害有多大?
  • @MonsterTruck:只是为了插入阶段? 50,000 个竞争插入不可能花费半小时。我强烈怀疑发生了其他事情。您可以在多大程度上隔离启动阶段以通过各种方式对其进行测试?
  • @MonsterTruck:开裂。如果花费超过一秒钟,我会感到非常惊讶:)
  • @MonsterTruck:对——这就是重点;插入所花费的时间——无论是否有争议——都应该是微不足道的。这就是让我觉得在“不到 10 分钟”与“超过 40 分钟”的场景中还有其他事情发生的原因。

标签: java concurrency hashmap


【解决方案1】:

如果您使用多个线程插入,即使键不同,您也绝对应该使用ConcurrentHashMap 或同步插入。普通的HashMap 对于并发写入来说根本不安全。假设两个线程都需要同时扩展内部表......即使它们使用不同的键,这也是一个根本性的问题。

现在,如果您真的真的有充分的证据表明在您的应用程序生命周期的其余时间使用 ConcurrentHashMap 会导致问题(我非常怀疑它确实如此),您也许可以构建一个并发哈希映射开始,在单个线程中将其转换为HashMap(甚至是来自Guava的不可变集合),确保“最终映射已发布”和“线程读取”之间存在发生前的障碍最终地图”。

【讨论】:

  • +1 避免使用 ConcurrentHashMap 的唯一方法是让每个线程更新一个仅由该线程使用的不同 Map。
  • OP 说插入只在启动时发生。如果地图是安全发布的,并且只有在所有插入之后,那么它应该没问题。我不相信 HashMap 会修改读取的任何字段。
  • @yshavit:是的,但他给人的印象是地图是由多个线程填充的——那是不安全的。
  • 哦,是的,我错过了子弹 #2。
【解决方案2】:

如果你有跨线程的独立键,你可以考虑独立映射。如果这是一个选项,每个线程都可以有自己的 HashMap,它不需要是线程安全的,只要它只被一个线程使用。

【讨论】:

  • 如果这是一个选项,它应该是最快的。只有在需要跨线程共享数据时,才应该使用共享的 ConcurrentHashMap。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多