当使用迭代器时解释集合的同步? [英] Explain synchronization of collections when iterators are used?

查看:142
本文介绍了当使用迭代器时解释集合的同步?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I understand that collections like the Hashtable are synchronized, but can someone explain to me how it works, and at what point(s) access is restricted to concurrent calls? For example, let's say I use some iterators like this:

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(),会发生什么?如果removeomething()删除一个尚未由dosomething1()中的并发循环处理的项目?

Can someone please explain if there are any pitfalls with me calling these functions at random from different threads? How does the iterator, in particular, do its synchronization, especially when it is using entrySet(), which would seem to also require synchronization? What happens if clear() is called while one of the loops is in progress? What if removesomething() removes an item that is not yet processed by a concurrent loop in dosomething1() ?

感谢任何帮助!

推荐答案

在Java中对集合的迭代不是线程安全的,即使您使用了一个同步包装器( Collections.synchronizedMap 。)):

Iteration over collections in Java is not thread safe, even if you are using one of the synchronized wrappers (Collections.synchronizedMap(...)):


用户必须在返回的
映射上手动同步遍历其任何集合视图:

It is imperative that the user manually synchronize on the returned map when iterating over any of its collection views:

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 作为他们的监视器:

Other calls to synchronized collections are safe, as the wrapper classes surround them with synchronized blocks, which use the wrapper collection as their monitor:

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

c $ c>是原始集合。

with collection being the original collection. This works for all methods exposed by a collection/map, except for the iteration stuff.

映射的键集合以同样的方式进行同步:同步包装器不返回原始密钥集。相反,它返回集合的原始密钥集的特殊同步包装。这同样适用于条目集和值集。

The key set of a map is made synchronized just the same way: the synchronized wrapper does not return the original key set at all. Instead, it returns a special synchronized wrapper of the collection's original key set. The same applies to the entry set and the value set.

这篇关于当使用迭代器时解释集合的同步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆