ConcurrentHashMap的KeySet迭代器是线程安全的吗?

时间:2013-10-25 08:04:52

标签: java multithreading

我只是想探索什么是ThreadSafe意味着什么?

以下是我的理解:

对我而言;允许多个线程同时访问集合;这与其同步无关。例如,没有synchronized关键字的任何方法;是线程安全的,意味着多个线程可以访问它。

开发人员可以选择在此方法上维护更多逻辑(同步),以便在多线程访问数据时保持数据完整性。这与线程安全是分开的。

如果我的上述陈述是假的;只需阅读以下JAVA DOC中的“ConcurrentHashMap:

  

keySet:视图的迭代器是一个永远不会抛出的“弱一致”迭代器   ConcurrentModificationException,并保证在构造迭代器时遍历元素,并且可能(但不保证)反映构造之后的任何修改。

上述声明称keySet迭代器不保证数据完整性;多线程正在修改集合。

你能否回答我,* ConcurrentHashMap的KeySet迭代器是线程安全的吗?

我对线程安全的理解是正确的吗?

3 个答案:

答案 0 :(得分:3)

java.util.concurrent包背后的一般想法是提供一组数据结构,这些数据结构提供线程安全访问而没有强大的一致性。这样,这些对象实现了更高的并发性,然后正确锁定了对象。

线程安全意味着,即使没有任何显式同步,也不会破坏对象。在HashTableHashMap中,某些方法是多线程访问的潜在问题,例如remove方法,它首先检查元素是否存在,然后将其删除。这些方法在ConcurrentHashMap中实现为原子操作,因此您不必担心会丢失一些数据。

但是,这并不意味着每个操作都会自动锁定此类。诸如putAll和迭代器之类的高级操作不同步。该课程不具备强大的一致性。保证操作的顺序和时间不会破坏对象,但不能保证生成准确的结果。

例如,如果您通过调用putAll同时打印对象,则可能会看到部分填充的输出。与新插入同时使用迭代器也可能无法反映所引用的所有插入。

这与线程安全不同。即使结果可能会让您大吃一惊,但您可以放心,不会丢失或意外覆盖任何内容,可以毫无问题地添加和删除元素。如果此行为足以满足您的要求,建议您使用java.util.concurrent类。如果您需要更多一致性,则需要使用java.util中的同步类或自己使用同步。

答案 1 :(得分:2)

  

keySet:视图的迭代器是一个“弱一致”的迭代器,它永远不会抛出ConcurrentModificationException,并保证遍历构造迭代器时存在的元素,并且可能(但不保证)反映构造后的任何修改

这就解释了,ConcurrentHashMap的 KeySet迭代器是线程安全的。

答案 2 :(得分:1)

根据您的定义,Set 返回的ConcurrentHashMap.keySet() 是线程安全的。

然而,正如你所包含的引文中所指出的,它可能以非常奇怪的方式起作用。

  1. 作为Set,条目可能随机显示和/或消失。即如果您在同一个对象上调用contains两次,则两个结果可能会有所不同。
  2. 作为Iterable,您可以在两个不同的线程中开始对其底层对象进行两次迭代,并发现两次迭代枚举不同的条目。
  3. 此外,contains和迭代可能也不匹配。
  4. 但是,如果您在保留Map的同时以某种方式锁定基础Set,则不会发生此活动,但需要这样做并不意味着结构不是线程安全