解释使用迭代器时集合的同步吗?

问题描述

Java中的集合迭代不是线程安全的,即使您使用的是同步包装器(Collections.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());
}

Java Collection Framework文档

对同步集合的其他调用是安全的,因为包装器类将它们包围在synchronized块中,这些块将包装器集合用作其监视器:

public int size() {
    synchronized( this ) {
        return collection.size();
    }
}

collection原始的收藏。这适用于集合/映射公开的所有方法,迭代方法除外。

映射的键集以相同的方式进行同步:同步的包装器根本不返回原始键集。相反,它返回集合原始键集的特殊同步包装器。条目集和值集也是如此。

解决方法

我了解像Hashtable这样的集合是同步的,但是有人可以向我解释它是 如何
工作的,在什么时候访问仅限于并​​发调用?例如,假设我使用了一些像这样的迭代器:

Hashtable<Integer,Integer> map = new Hashtable<Integer,Integer>();

void dosomething1(){
    for (Iterator<Map.Entry<Integer,Integer>> i = map.entrySet().iterator(); i.hasNext();){
        // do something
    }
}
void dosomething2(){
    for (Iterator<Map.Entry<Integer,Integer>> i = map.entrySet().iterator(); i.hasNext();){
        // do something
        // and remove it
        i.remove();
    }
}
void putsomething(int a,int b){
    map.put(a,b);
}
void removesomething(int a){
    map.remove(a);
}
var clear(){
    map = new Hashtable<Integer,Integer>();
}

有人可以解释一下从不同线程中随机调用这些函数是否有陷阱吗?特别是,迭代器如何进行同步,尤其是在使用entrySet()时,似乎也需要同步?如果在循环之一进行时调用clear()会发生什么?如果removesomething()删除了dosomething1()中并发循环尚未处理的项目,该怎么办?

谢谢你的帮助!