【问题标题】:Java Concurrency and Add-Only HashMapsJava 并发和 Add-Only HashMap
【发布时间】:2011-04-19 04:51:03
【问题描述】:

我正在编写一个广泛使用大型 HashMap 的程序。它是多线程的,所以我在访问它时使用了读写锁。但是,它有一个我想利用的特殊属性。

在将数据“放入”到 HashMap 后,该数据从不更改。曾经。每当对该数据结构的状态进行更改时,它实际上只是创建了新的“一代”结构,而旧的则保持不变。

也就是说,在另一个线程正在写入一个值的同时从 HashMap 读取一个值是否安全,知道另一个线程将永远写入你正在写入的值阅读?有没有一些简单的哈希表结构可以给我这种保证?

【问题讨论】:

  • 您是否想在以某种方式修改哈希图后对其进行深度复制?正如@Brian Roach 指出的那样,这些新副本是只读的,不需要 MT 同步。但是,您可能需要同步才能选择正确的“版本”来阅读。或者,也许我错过了什么......

标签: java multithreading locking hashmap


【解决方案1】:

不是真的。因为您可以写入它,所以您可能会在这样做时触发底层数组的调整大小。如果您在另一个线程的读取过程中触发调整大小,您真的会影响它准确查找数据的能力!

【讨论】:

  • 他已经声明他不会写信给它。没有理由为只读锁定/同步
  • 不,他不是这么说的。他说他不会覆盖它。假设他添加了EthanObject eo。然后他做出改变。他不会在地图中覆盖eo,而是改为创建EthanObject eo2 并添加eo2
  • 不,我 正在 写入 HashMap,只是写入的值与我正在读取的值不同。我明白了 gloomcoder 的意思——你能推荐一个优雅地调整大小的数据结构,这样它不会破坏当前读取的逻辑吗?
  • @Ethan 不幸的是,我不能。不过,编写自己的代码并不是不可想象的(或困难的)。问题是它会涉及底层数组结构的副本,使insert() 成为O(n) 调用。
【解决方案2】:

问题不在于哈希图中的数据,而在于您在插入某些内容时正在修改哈希图本身;它的结构。您不能使用标准 HashMap 一次对多个线程执行此操作。

java 并发包确实提供了一个线程安全的 hashtmap:

http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentHashMap.html

在内部,这将使用线程安全的非锁定方法。

【讨论】:

  • 我认为并发哈希映射同时使用锁定和非锁定方法来保证线程安全。锁定方法不会锁定整个地图,而是锁定地图的一部分。
  • @richs - 我必须阅读源代码,但大多数并发包依赖于 CAS 而不是锁,并且 javadocs 说 即使所有操作都是线程安全的,检索操作不需要锁定,也不支持以阻止所有访问的方式锁定整个表。两个并发插入可能涉及锁定,但总的来说,我认为对他来说,使用重量级锁进行所有访问的开销应该更少。
【解决方案3】:

我知道您已声明它不会被覆盖,但值得考虑使用 ConcurrentHashMap,因为您不再需要“锁定”代码。

这个特殊的映射(从 java 1.5 开始)保证你永远不会得到 ConcurrentModificationException,因为它会返回你最后的“完成”写入。

http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html

它对于多个并发读取也非常快。有关更多信息,请参阅这篇文章:

http://www.ibm.com/developerworks/java/library/j-jtp07233/index.html#N101CD

其他需要注意的事项:它不允许空键/值,并且它有另一个方便的方法,putIfAbsent。

HTH

【讨论】:

    【解决方案4】:

    您可以使用persistentMap代替HashMap,然后每个写入者在添加新对象并用新对象替换对映射的引用时都必须锁定它,但读者总是可以从“当前”版本中读取(可能找不到他们正在寻找的值,因为它是同时添加的。

    请注意,必须以原子方式读取和写入对 Map 的引用。

    【讨论】:

      猜你喜欢
      • 2018-12-15
      • 1970-01-01
      • 1970-01-01
      • 2013-07-28
      • 2021-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多