【问题标题】:Is values() of ConcurrentHashMap thread safe?ConcurrentHashMap 线程的 values() 是否安全?
【发布时间】:2019-09-22 18:55:54
【问题描述】:

我是 Java8 的新手,正在解决多个线程 (~10) 正在将值写入并发哈希映射的问题。我有另一个专用线程,它读取并发哈希映射中存在的所有值并返回它们(每 30 秒)。迭代 values() 方法的结果是在不获取并发修改异常的情况下获取结果的推荐方法吗?

注意:我完全可以获取过时的数据

我查看了官方文档,上面写着:

检索操作一般不会阻塞,因此可能与更新操作重叠。检索反映了最近完成的更新操作在其开始时保持的结果。对于 putAll 和 clear 等聚合操作,并发检索可能仅反映插入或删除某些条目。类似地,迭代器、拆分器和枚举返回反映哈希表在创建迭代器/枚举时或之后的某个时间点的状态的元素。它们不会抛出 ConcurrentModificationException。

但是 values() 方法的文档说:

返回此映射中包含的值的集合视图

下面的代码线程安全吗?

for (String name: myMap.values()) {
     System.out.println("name": + name);
}

【问题讨论】:

  • 是的,它是线程安全的。
  • 您刚刚引用了答案:“同样,迭代器、拆分器和枚举返回的元素反映了在迭代器/枚举创建时或之后的某个时刻哈希表的状态”我>。该声明涵盖entrySet()keySet()keys()values()elements()

标签: java concurrency concurrenthashmap


【解决方案1】:

在不获取ConcurrentModificationException 的情况下,迭代values() 方法的结果是推荐的获取结果的方法吗?

是的。这是推荐的方式,你不会得到ConcurrentModificationException

正如包级 javadoc 所述:

大多数并发 Collection 实现(包括大多数队列)也不同于通常的 java.util 约定,因为它们的 Iterators 和 Spliterators 提供弱一致而不是快速失败遍历:

  • 它们可能与其他操作同时进行
  • 他们永远不会抛出 ConcurrentModificationException
  • 保证它们只遍历构建时存在的元素一次,并且可能(但不保证)反映构建后的任何修改。

下面的代码线程安全吗?

  for (String name: myMap.values()) {
       System.out.println("name": + name); 
  }

是的……有一些资格。

线程安全实际上意味着代码在多线程应用程序中按照其指定的行为工作。问题是你没有清楚地说明你期望代码实际做什么

我们可以说如下:

  1. 迭代将根据前面所述的保证查看值。
  2. 内存模型保证意味着不应有任何带有陈旧值的讨厌行为...除非您在将值对象放入映射后对其进行变异。 (如果您这样做,则需要实现对象的方法以应对这种情况;例如,它们可能需要为 synchronized。这对于 String 值没有实际意义,因为它们是不可变的。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-20
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 2018-01-31
    相关资源
    最近更新 更多