【问题标题】:Fast thread-safe read optimised Map[Long, _]快速线程安全读取优化 Map[Long, _]
【发布时间】:2014-02-25 21:50:58
【问题描述】:

我正在寻找带有Long 键的快速Map 的建议。它将有很多读访问和相当小的写/更新访问。因此,性能应侧重于读取 (get) 访问。它必须是线程安全的。一些想法:

  1. 常规的collection.Map[Long, _] 必须框键
  2. 裸露的collection.mutable 必须一直包装synchronized,这会惩罚读取访问权限
  3. 如果存储在@volatile var 中,裸骨collection.immutable 可能具有不同步的读取访问权限。更新可以同步。
  4. 也许是来自 Scala-STM 的 TMap?但是Ref[Map[Long, _]] 可能也一样好,因为 STM 中应该允许并发读取

对我来说,3 号听起来最好?

【问题讨论】:

  • 我认为 volatile 会影响集合本身,而不是其内容。

标签: multithreading scala collections


【解决方案1】:

有一个不可变的LongMap,而2.11 将有一个可变的LongMap。后者不是线程安全的,但您可以包装访问(可能使用来自java.util.concurrent 的读写锁,如果您主要在阅读并且可以通过可能的死锁进行推理)。如果您有很多争用,您不太可能比仅使用java.util.concurrent.ConcurrentHashMap 做得更好;线程问题将比一些额外的装箱更昂贵。

【讨论】:

  • Note: This class is as of 2.8 largely superseded by HashMap. 上的 LongMap 主要是什么?
  • 没错,我看到了关于过时的注释。另外,由于它在常规的 scala.collection 类型层次结构中,我认为它仍然会将键装箱,对吧?
  • @0__ - 我对immutable.LongMap 不是很熟悉,但它不应该将键装箱,除非您在通用上下文中使用(在这种情况下,它会装箱和拆箱)。确实,immutable.LongMap 没有做太多工作。不过,可变的是全新的。
【解决方案2】:

collection.Map 默认情况下不是线程安全的,但必须使用 SynchronizedMap 特征,它只是锁定所有访问 - 性能方面不太好,可能比简单的 ConcurrentHashMap 慢。

使用不可变映射和在更新时被替换的 volatile 变量会起作用,并且可能是明智的读取方式最便宜的选择(不能比简单的 volatile 读取便宜)。不过更新的时候很贵。

不知道 Scala 的 STM 有多好,所以当然也值得一试。

您绝对应该考虑的一个选项是 Cliff 的非阻塞哈希图,see here。它确实有一个长版本,因此您可以避免装箱,并且在性能方面很难被击败(取决于情况,与 java stdlib 中的 ConcurrentHashMap 相比,它的速度更快到极快,这再次比仅使用普通哈希图和锁定要快得多围绕每个访问)。

【讨论】:

  • 感谢提及java.util.concurrent.ConcurrentHashMap,在性能测试中可能是一个很好的比较
【解决方案3】:

听起来像是常规 HashMap 或 fastutil Long2Object mapReentrantReadWriteLock 的良好使用。该锁将允许您同时打开多个读锁,但写锁必须是独占的。我仍然会将它与 ConcurrentHashMap 进行基准测试,因为众所周知它的实现非常好。

哇!您可能想要一个 Scala 答案,而不是 Java 风格。

【讨论】:

  • 谢谢!我不在乎它是 Java 还是 Scala,只要它紧凑且开源即可。
猜你喜欢
  • 1970-01-01
  • 2011-04-06
  • 1970-01-01
  • 2011-07-13
  • 2011-09-03
  • 2012-06-09
  • 2010-12-23
  • 2013-02-10
  • 2021-06-06
相关资源
最近更新 更多