在同步集合中安全使用迭代器

时间:2014-05-27 07:41:46

标签: java collections iterator synchronization

在有关synchronizedMap的教程中,我遇到了以下代码(教程中的注释):

Map m = Collections.synchronizedMap(new HashMap());
...
Set s = m.keySet();  // Needn't be in synchronized block
...
synchronized(m) {  // Synchronizing on m, not s!
    Iterator i = s.iterator(); // Must be in synchronized block
    while (i.hasNext())
          foo(i.next());
}

我在源代码中看到迭代器方法没有被synchronized部分包装。没关系。

我害怕得到意想不到的东西

Set s = m.keySet();  
// Could happen something unexpected here ?
synchronized(m) { 

请说明为什么这段代码是安全的?

 synchronized(m) {  // Synchronizing on m, not s!
        Set s = m.keySet();  // Needn't be in synchronized block
        Iterator i = s.iterator(); // Must be in synchronized block
        while (i.hasNext())
              foo(i.next());
    }

这种同步化是否过度?

1 个答案:

答案 0 :(得分:0)

虽然Collections.synchronizedMap()保证包装映射上的每个操作都是线程安全的,但它并不能保证迭代它。当你在迭代时在地图上同步时,你要保证另一个线程在1个线程迭代它时不能访问地图(毕竟,你想确保以原子方式迭代它)。 / p>

如果没有这种同步,另一个线程可以在i.hasNext() while循环之间执行一个或多个操作。

实现是集合本身的synchronizedMap()包装器同步(在代码m中),因此使用synchronized(m)获取对象监视器可确保另一个线程在访问之前无法访问它迭代已完全执行。