1

以下引文的最后一点对我来说不是很清楚:

检索操作(包括 get)一般不会阻塞,因此可能与更新操作(包括 put 和 remove)重叠。检索反映了最近完成的更新操作在其开始时保持的结果。对于 putAll 和 clear 等聚合操作,并发检索可能仅反映插入或删除某些条目。

为什么只针对某些条目?

4

3 回答 3

5

第一部分和最后一部分必须一起阅读才能理解。分解它,我们得到:

  • 检索操作(包括get)一般不会阻塞,因此它们可能与更新操作重叠
  • 检索反映了最近完成的更新操作在开始时保持的结果

现在,考虑在以下情况下会发生什么putAll(这是 ConcurrentHashMap.java 源代码):

for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
    put(e.getKey(), e.getValue());

请注意,它将每个条目循环添加到地图中。如果您调用putAll100 个条目,并且在 50% 的过程中,另一个线程尝试get从映射中获取一个值,那么此时只有 50 个条目putAll可用。

具体来说:文档没有通知您特定条目将不可用,只是在您调用另一个线程之前整个聚合操作可能尚未完成get,因为它们彼此不同步。

于 2013-07-15T13:25:41.280 回答
0

putAll并且clear不是原子操作。因此,如果一个线程调用putAll来放置几个条目,而另一个线程并行检索值,它可能会看到putAll操作的中间状态。putAll在方法完成之前,地图不会阻塞。(与清除相同 - 可以在清除操作并行运行时检索值

于 2013-07-15T13:26:50.177 回答
0

只有“一些”更改可能会被看到,因为另一个线程可能会在 or 期间访问地图,这两者都需要许多步骤才能完成,而它只完成了一部分putAll()clear()

于 2013-07-15T13:25:20.107 回答