以下引文的最后一点对我来说不是很清楚:
检索操作(包括 get)一般不会阻塞,因此可能与更新操作(包括 put 和 remove)重叠。检索反映了最近完成的更新操作在其开始时保持的结果。对于 putAll 和 clear 等聚合操作,并发检索可能仅反映插入或删除某些条目。
为什么只针对某些条目?
以下引文的最后一点对我来说不是很清楚:
检索操作(包括 get)一般不会阻塞,因此可能与更新操作(包括 put 和 remove)重叠。检索反映了最近完成的更新操作在其开始时保持的结果。对于 putAll 和 clear 等聚合操作,并发检索可能仅反映插入或删除某些条目。
为什么只针对某些条目?
第一部分和最后一部分必须一起阅读才能理解。分解它,我们得到:
现在,考虑在以下情况下会发生什么putAll
(这是 ConcurrentHashMap.java 源代码):
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
put(e.getKey(), e.getValue());
请注意,它将每个条目循环添加到地图中。如果您调用putAll
100 个条目,并且在 50% 的过程中,另一个线程尝试get
从映射中获取一个值,那么此时只有 50 个条目putAll
可用。
具体来说:文档没有通知您特定条目将不可用,只是在您调用另一个线程之前整个聚合操作可能尚未完成get
,因为它们彼此不同步。
putAll
并且clear
不是原子操作。因此,如果一个线程调用putAll
来放置几个条目,而另一个线程并行检索值,它可能会看到putAll
操作的中间状态。putAll
在方法完成之前,地图不会阻塞。(与清除相同 - 可以在清除操作并行运行时检索值)。
只有“一些”更改可能会被看到,因为另一个线程可能会在 or 期间访问地图,这两者都需要许多步骤才能完成,而它只完成了一部分。putAll()
clear()