当前位置: 首页 > 知识库问答 >
问题:

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

岑叶秋
2023-03-14

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

以下是我的理解:

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

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

如果我的上述陈述是错误的;只需阅读下面的 JAVA DOC for 'ConcurrentHashMap:

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

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

能否请您回答我,*是KeySet迭代器的并发HashMap是线程安全的吗?

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

共有3个答案

洪开诚
2023-03-14

根据您的定义,由< code > concurrent hashmap . keyset()返回的< code >集合是线程安全的。

然而,它可能以非常奇怪的方式运行,正如您在引用中所指出的那样。

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

但是,如果您在拥有< code >集合的同时,以某种方式锁定基础< code>Map以防修改,则此活动不会发生,但是需要这样做并不意味着该结构不是线程安全的。

费德宇
2023-03-14

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

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

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

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

这不同于线程安全。尽管结果可能会让您感到惊讶,但您可以放心,没有任何东西会丢失或被意外覆盖,在对象中添加和删除元素不会有任何问题。如果这种行为足以满足您的需求,建议您使用< code > Java . util . concurrent 类。如果您需要更多的一致性,那么您需要使用来自< code>java.util的同步类或者自己使用同步。

吴升
2023-03-14

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

这本身就解释了,并发HashMap的KeySet迭代器是线程安全的。

 类似资料:
  • 问题内容: 在javadoc中,ConcurrentHashMap如下: 检索操作(包括get)通常不会阻塞,因此可能与更新操作(包括put和remove)重叠。检索反映了自启动以来最新完成的更新操作的结果。对于诸如putAll和clear的聚合操作,并发检索可能仅反映某些条目的插入或删除。同样,迭代器和枚举返回的元素反映了在创建迭代器/枚举时或此后某个时刻哈希表的状态。他们不抛出Concurre

  • HashMap的底层算法采用了链地址法来解决哈希冲突 哈希表 在数据结构中有一种称为哈希表的数据结构,它实际上是数组的推广。如果有一个数组,要最有效的查找某个元素的位置,如果存储空间足够大,那么可以对每个元素和内存中的某个地址对应起来,然后把每个元素的地址用一个数组(这个数组也称为哈希表)存储起来,然后通过数组下标就可以直接找到某个元素了。这种方法术语叫做直接寻址法。这种方法的关键是要把每个元素和

  • 假设我有std::vector和两个线程。 第一个线程正在处理擦除函数,而第二个线程在for循环中 这种情况是线程安全的吗? 第二个线程会继续运行还是抛出异常?

  • 问题内容: 我有一个多线程程序,在其中创建生成器函数,然后将其传递给新线程。我希望它本质上是共享/全局的,以便每个线程都可以从生成器获取下一个值。 使用这样的生成器是否安全?还是会遇到从多个线程访问共享生成器的问题/情况? 如果不是,是否有更好的方法来解决此问题?我需要可以在列表中循环并为任何线程调用它生成下一个值的东西。 问题答案: 它不是线程安全的;同时调用可能交错,并与局部变量混淆。 常用的

  • 问题内容: 我正在制作一个需要一堆日记条目并计算总和的应用程序。 下面的方法是在有 多个线程 调用该方法时是线程/并发安全的。我想确保每个电话都能正确更新总数。 如果不安全,请说明为确保线程安全我该怎么做。 我需要获取/放置还是有更好的方法? 非常感谢! 更新: 谢谢大家的回答,我已经知道上面的代码 不是线程安全的 。 感谢Vint建议使用替代。我以前用来保存整数和,我想知道BigDecimal是

  • 问题内容: 在中,此变量被声明为是我的问题,在某些调用之后检查值还是在多线程代码中使用perror()是安全的。这是线程安全变量吗?如果没有,那还有什么选择呢? 我在x86体系结构上将Linux与gcc一起使用。 问题答案: 是的,它是线程安全的。在Linux上,全局errno变量是特定于线程的。POSIX要求errno必须是线程安全的。 参见http://www.unix.org/whitepa