使类上的所有方法单独同步不会使这些方法的聚合(在组中调用它们)成为线程安全的。通过将 包装Iterator在一个同步块中,您可以保护迭代器的特定实例,使其不被多个线程调用的单个方法与其他调用穿插。
如果我.add()在安全的情况下调用一次,如果我需要.add()多次调用以完成一个逻辑语句,则不能保证其他人没有在我的.add()调用之间添加其他内容或删除其他内容,除非我阻止其他所有内容调用.add()(或任何其他方法)通过synchronizing代表集合的变量。
对集合上的Iterator各个方法进行多次调用,它们都必须包装在一个synchronized块中,以使它们作为单一transaction的一种执行。检查执行的源代码 Iterator你会明白我的意思。这是List它对底层实现进行多次单独调用的源代码,因此它们都需要由同一线程以不间断的顺序执行才能确定。
@Override
public Iterator<A> iterator() {
if (tail == null)
return emptyIterator();
return new Iterator<A>() {
List<A> elems = List.this;
public boolean hasNext() {
return elems.tail != null;
}
public A next() {
if (elems.tail == null)
throw new NoSuchElementException();
A result = elems.head;
elems = elems.tail;
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
源代码显示AbstractList.iterator()了更复杂的逻辑,可以进行多次调用。
更好的包装器是将它们包装在Immutable集合中,然后您保证没有其他东西可以改变调用之间的基础集合。