我正在阅读B. Goetz Java Concurrency In Practice现在我在关于线程安全集合的部分。他描述了所谓的隐藏迭代器"这可能会抛出public class HiddenIterator{
@GuardedBy("this")
private final Set<Integer> set = new HashSet<Integer>();
public synchronized void add(Integer i){ set.add(i); }
public synchronized void remove(Integer i){ set.remove(i); }
public void addTenThings(){
Random r = new Random();
for(int i = 0; i < 10; i++)
add(r.nextInt());
System.out.println("DEBUG: added ten elements to set " + set)
}
}
。以下是他发布的例子:
addTenThings()
现在,ConcurrentModificationException
可能会抛出set
,因为打印set
的内容涉及迭代它。但他提出以下建议来处理它:
如果HiddenIterator使用synchronizedSet包装HashSet, 封装同步,不会发生这种错误。
我不太明白。即使我们将NotThreadSafe
包装到synchronized-wrapper中,该类仍将保持{{1}}。他是什么意思?
答案 0 :(得分:6)
这是因为Collections.synchronizedSet
同步每个方法,包括toString
。实际上,如果你试图迭代一个包装的手动,你可以获得ConcurrentModificationException
,所以你必须自己同步手动迭代。但是做隐藏迭代的方法已经做到了,所以你至少不必担心这一点。以下是JDK源代码中的相应代码:
public String toString() {
synchronized (mutex) {return c.toString();}
}
此处,mutex
在包装类的构造函数中初始化为this
,因此它基本上是synchronized (this)
。