java – ConcurrentHashMap包含值,但size()方法返回0

遇到ConcurrentHashMap的奇怪行为:首先,使用比较和设置操作(如putIfAbsent()和remove()),几个线程会同时修改映射.经过一段时间(几十秒甚至一分钟)后,另一个线程使用两种方法检查地图是否为空:

>调用myMap.isEmpty()方法
>试图查看迭代器中是否有任何条目:myMap.entrySet().iterator().hasNext()

令人惊讶的是,这两种方法给出了不同isEmpty()返回true,iterator.hasNext()在此之后返回true.执行调用时没有任何暂停,此时不对地图执行写操作.

请注意,根据日志,isEmpty()返回false并且iterator.hasNext()同时返回false时不会出现这种情况.因此,总是isEmpty()方法不会“看到”地图中的任何条目.

不知道这是否是ConcurrentHashMap的预期行为.

文件指出:

Bear in mind that the results of aggregate status methods including size, isEmpty, and containsValue are typically useful only when a map is not undergoing concurrent updates in other threads. Otherwise the results of these methods reflect transient states that may be adequate for monitoring or estimation purposes, but not for program control.

这使得在没有正在进行的写操作时,期望像size()和isEmpty()这样的方法返回与地图的实际内容一致的值.

最佳答案 ConcurrentHashMap.getEntrySet()的
javadoc告诉您从集合中获取的迭代器是弱一致的.

java.util.concurrent包的Javadoc解释了“弱一致”的含义:

… their Iterators and Spliterators provide weakly consistent rather than fast-fail traversal:

  • they may proceed concurrently with other operations
  • they will never throw ConcurrentModificationException
  • they are guaranteed to traverse elements as they existed upon construction exactly once, and may (but are not guaranteed to) reflect any modifications subsequent to construction.

最后一颗子弹是重要的.它告诉您迭代器是创建迭代器时映射中的内容的视图.如果随后更改了地图的内容,迭代器的内容将不会更改.

点赞