3

我只是想探索一下ThreadSafe 是什么意思?

以下是我的理解:

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

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

如果我的上述陈述是错误的;只需阅读下面的 JAVA DOC 以获取 `ConcurrentHashMap:

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

上面的声明说keySet迭代器不会保证数据的完整性;而多线程正在修改集合。

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

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

4

3 回答 3

3

该包背后的总体思想java.util.concurrent是提供一组数据结构,这些数据结构提供线程安全访问,但没有强一致性。通过这种方式,这些对象实现了更高的并发性,然后正确锁定了对象。

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

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

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

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

于 2013-10-25T08:32:27.877 回答
3

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

这本身就说明了 ConcurrentHashMap 的 KeySet 迭代器是线程安全的。

于 2013-10-25T08:25:13.317 回答
1

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

但是,正如您在引用中指出的那样,它可能会以非常奇怪的方式起作用。

  1. 作为Set,条目可能会随机出现和/或消失。即,如果您contains对同一个对象调用两次,则两个结果可能会有所不同。
  2. 作为一个,Iterable您可以在两个不同的线程中开始其底层对象的两次迭代,并发现这两次迭代枚举了不同的条目。
  3. 此外,contains迭代也可能不匹配。

Map但是,如果您在持有您的情况下以某种方式锁定底层不被修改,则不会发生此活动,Set但需要这样做并不意味着该结构不是线程安全的。

于 2013-10-25T08:38:26.947 回答