3

我正在阅读关于ConcurrentHashMap.

我读到它提供了一个不需要同步的迭代器,甚至允许在迭代期间修改 Map,因此不会有ConcurrentModificationException.

我想知道这是否是一件好事,因为ConcurrentHashMap在迭代期间我可能无法获得更早放入的元素,因为另一个线程可能已经更改了它。

我的想法正确吗?如果是,是好是坏?

4

3 回答 3

4

我想知道这是否是一件好事,因为在迭代过程中我可能无法获得之前放入 ConcurrentHashMap 的元素,因为另一个线程可能已经更改了它。

我不认为这应该是一个问题 - 如果您使用同步并且执行迭代的线程恰好在插入值的线程之前获取锁并执行它的循环,则相同的语句是正确的。

如果您需要在线程之间进行某种协调以确保某些操作发生在(并且仅在)另一个操作之后,那么您仍然需要管理这种协调,无论使用的 Map 类型如何。

于 2013-06-04T14:39:57.980 回答
1

通常,ConcurrentHashMap弱一致性迭代器就足够了。相反,如果您想要一个强一致的迭代器,那么您有几个选择:

  1. ctrie一个哈希数组映射的 trie,提供恒定时间快照。有可用于数据结构的Java 源代码。
  2. Clojure 有一个您可以使用的PersistentHashMap - 这使您可以遍历数据的快照。
  3. 使用本地数据库,例如HSQLDB来存储数据,而不是使用ConcurrentHashMap. 使用 key|timestamp 的复合主键,当您“更新”一个值时,您将使用当前时间戳存储一个新条目。要获取迭代器,请使用where timetamp < System.currentTimeMillis()子句检索结果集,然后迭代结果集。

在任何一种情况下,您都在迭代快照,因此您有一个高度一致的迭代器;在前一种情况下,您冒着内存不足的风险,而后一种情况是一个更复杂的解决方案。

于 2013-06-04T14:46:20.280 回答
0

concurrent -anything的全部意义在于您承认并发活动,并且不相信所有访问都是序列化的。对于大多数集合,如果不努力,您就不能期望元素间的一致性。

如果您不关心查看最新数据,但想要一致的(但可能是旧的)数据视图,请查看诸如Finger Trees 之类的纯功能结构。

于 2013-06-04T14:48:25.597 回答