Explain synchronization of collections when iterators are used?(解释使用迭代器时集合的同步?)
问题描述
我知道像 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() 会发生什么?如果 removesomething() 删除了一个尚未被 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集合框架文档
对同步集合的其他调用是安全的,因为包装器类用 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();
}
}
collection
是原始集合.这适用于集合/映射公开的所有方法,迭代的东西除外.
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.
这篇关于解释使用迭代器时集合的同步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:解释使用迭代器时集合的同步?
基础教程推荐
- 如何强制对超级方法进行多态调用? 2022-01-01
- 如何对 HashSet 进行排序? 2022-01-01
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01
- 在螺旋中写一个字符串 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01