需要在可以避免的情况下在迭代时手动同步 Synchronized 列表?

我的问题是关于 synchronizedList 方法集合类.

My question is about synchronizedList method Collections Class.

Javadocs 说:

Javadocs say:

用户在迭代返回的列表时必须手动同步:

List list = Collections.synchronizedList(new ArrayList());
      ...
synchronized(list) {
   Iterator i = list.iterator(); // Must be in synchronized block
   while (i.hasNext())
      foo(i.next());
}

虽然其他方法不需要手动同步.我查看了 Collections 类的源代码并且发现 shyncronization 已经对 add 等所有方法进行了处理

Though manually synchroniziation is not required for other methods. I looked into the source code of Collections class and found shyncronization has already been taken care for all methods like add

public boolean add(E e) {
   synchronized(list) {return c.add(e);}
}

但不适用于迭代器方法.我认为迭代器方法也可以以相同的方式处理同步如上述方法(它可以避免额外的工作,即程序员的手动同步).我确定在那里一定是背后的一些具体原因,但我想念它?

but not for iterator method. I think iterator method could have also handled synchronization in the same fashion as above method (it would have avoided the extra work i.e manual synchronization for programmers). i am sure there must be some concrete reason behind it but i am missing it?

public Iterator<E> iterator() {
   return c.iterator(); // Must be manually synched by user!
}

一种避免程序员手动同步的方法

public Iterator<E> iterator() {
   synchronized(list) {
       return c.iterator(); // No need to manually synched by user!
   }
}

推荐答案

我认为迭代器方法也可以以与上述方法相同的方式处理同步

I think iterator method could have also handled synchronization in the same fashion as above method

不,绝对不能.

迭代器无法控制您的代码在调用其上的各个方法之间执行的操作.这才是重点.您的迭代代码将重复调用 hasNext()next(),并且在这些调用期间同步 是可行的但无关紧要 - 重要的是没有其他代码尝试在整个迭代过程中修改列表.

The iterator has no control over what your code does between calls to the individual methods on it. That's the point. Your iteration code will call hasNext() and next() repeatedly, and synchronization during those calls is feasible but irrelevant - what's important is that no other code tries to modify the list across the whole time you're iterating.

所以想象一个时间表:

t = 0: call iterator()
t = 1: call hasNext()
t = 2: call next()
// Do lots of work with the returned item
t = 10: call hasNext()

迭代器无法在 t=2 结束对 next() 的调用和 t=10 对 hasNext() 的调用之间进行同步.因此,如果另一个线程试图(比如说)在 t=7 时向列表中添加一个项目,那么迭代器是如何阻止它这样做的呢?

The iterator can't synchronize between the end of the call to next() at t=2 and the call to hasNext() at t=10. So if another thread tries to (say) add an item to the list at t=7, how is the iterator meant to stop it from doing so?

这是同步集合的整体问题:每个单个操作都是同步的,而通常您希望整个大块操作都同步.

This is the overall problem with synchronized collections: each individual operation is synchronized, whereas typically you want a whole chunky operation to be synchronized.

相关文章