2

Collections.synchronizedCollection(map)如果在迭代时必须同步代码,那么用 包装地图有什么意义?

  Collection<Type> c = Collections.synchronizedCollection(myCollection);
 synchronized(c) {
        for (Type e : c)
            foo(e); }

包装好后,不应该是线程安全的吗?

4

3 回答 3

3

如果在迭代时必须同步代码,那么用 Collections.synchronizedCollection(map) 包装地图有什么意义?

使单个操作线程安全。(我个人认为总的来说这是一个坏主意,但那是另一回事。这不是没有意义的,只是有用性有限。)

包装好后,不应该是线程安全的吗?

对于任何单独的操作,是的。但是迭代涉及许多步骤 - 虽然每个单独的步骤都将同步,但可以在步骤之间修改集合,从而使迭代器无效。不要忘记您的循环已扩展为:

for (Iterator<Type> iterator = c.iterator(); iterator.hasNext(); ) {
    Type e = iterator.next();
    ...
}

如果您需要迭代是线程安全的,则应使用java.util.concurrent... 中的集合之一,同时注意有关在迭代期间修改集合是否保证的警告。

于 2013-07-06T12:12:49.863 回答
0

包装之后,每个单独的方法都是线程安全的,但是迭代涉及重复调用方法(迭代器,然后是返回的迭代器上的下一个和 hasNext),并且这些方法之间没有同步。这就是您需要同步迭代的原因。

您还需要使用同步集合(而不仅仅是围绕迭代代码进行同步),因为否则添加或删除项目的方法将不会同步,因此即使您使用了同步块,也可能在迭代时进行修改。

于 2013-07-06T12:13:47.613 回答
0

添加到@jonskeet 的@jule 的答案,您应该考虑使用不需要锁定迭代的ConcurrentHashMaphttp://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentHashMap.html )。

于 2013-07-06T12:17:01.627 回答