ConcurrentHashMap线程的values()安全吗?

时间:2019-05-04 13:47:38

标签: java concurrency concurrenthashmap

我是Java8的新手,正在研究一个问题,其中多个线程(〜10个)正在将值写入并行哈希表。我还有另一个专用线程,该线程读取并发哈希映射中存在的所有值并返回它们(每30秒一次)。是否在values()方法的结果上进行迭代是获取结果的推荐方法,而又没有获得并发修改异常?

注意:获取陈旧数据完全可以

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

检索操作通常不会阻塞,因此可能与更新操作重叠。检索反映了自发生以来最新完成的更新操作的结果。对于诸如putAll和clear的聚合操作,并发检索可能仅反映某些条目的插入或删除。同样,迭代器,拆分器和枚举返回的元素反映了在创建迭代器/枚举时或此后某个时刻哈希表的状态。他们不会抛出ConcurrentModificationException。

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

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

下面的代码线程安全吗?

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

1 个答案:

答案 0 :(得分:2)

  

是否遍历values()方法的结果而不是获得ConcurrentModificationException的获取结果的推荐方法?

是的。这是推荐的方法,您不会得到ConcurrentModificationException

如包级javadoc所述:

  

大多数并发Collection实现(包括大多数Queue)也与通常的java.util约定不同,它们的迭代器和拆分器提供了弱一致性而不是快速失败遍历:

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

  

下面的代码线程安全吗?

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

是的...具有某些资格。

线程安全实际上意味着代码在多线程应用程序中根据其指定的行为工作。问题是您没有清楚说明代码的实际作用

我们可以说的是以下内容:

  1. 迭代将看到与先前说明的保证相同的值。
  2. 内存模型保证意味着不应该有具有过时值的讨厌行为...除非您在将值对象放入地图后对其进行突变。 (如果这样做,则需要实现该对象的方法来解决该问题;例如,它们可能需要为synchronized。这对于String值来说是没有意义的,因为它们是不可变的。)