我正在阅读B. Goetz Java Concurrency In Practice,现在我正处于关于线程安全集合的部分.他描述了可能抛出的所谓"隐藏的迭代器" ConcurrentModificationException
.以下是他发布的例子:
public class HiddenIterator{ @GuardedBy("this") private final Setset = new HashSet (); 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
的内容涉及迭代而抛出.但他提出以下建议来处理它:
如果HiddenIterator使用synchronizedSet包装HashSet,封装同步,则不会发生此类错误.
我不太明白.即使我们包装set
成同步包装器,该类仍将保留NotThreadSafe
.他的意思是什么?
这是因为Collections.synchronizedSet
同步每个方法,包括toString
.实际上,如果你试图手动迭代一个包装集,你就可以得到ConcurrentModificationException
,所以你必须自己同步手动迭代.但是做隐藏迭代的方法已经做到了,所以至少你不必担心.以下是JDK源代码的相应代码:
public String toString() { synchronized (mutex) {return c.toString();} }
这里,在包装类的构造函数中mutex
初始化this
,所以它基本上是synchronized (this)
.