Java 当synchronizedList()或向量已经同步时,为什么还需要外部同步?

Java 当synchronizedList()或向量已经同步时,为什么还需要外部同步?,java,multithreading,arraylist,synchronization,thread-safety,Java,Multithreading,Arraylist,Synchronization,Thread Safety,ArrayList未同步。但是有一种方法可以获得同步的,如java.util.ArrayList的JavaDoc中所述: List list = Collections.synchronizedList(new ArrayList(...)); 在java.util.CollectionsJavaDoc中,您可以看到“用户在迭代返回列表时必须手动同步它:” 使用同步的ArrayList会导致额外的工作,为什么不使用 java.util.Vector是否改为?使用这种方法有优势吗 我在上找到了这

ArrayList未同步。但是有一种方法可以获得同步的,如
java.util.ArrayList
的JavaDoc中所述:

List list = Collections.synchronizedList(new ArrayList(...));
java.util.Collections
JavaDoc中,您可以看到“用户在迭代返回列表时必须手动同步它:

使用同步的ArrayList会导致额外的工作,为什么不使用
java.util.Vector
是否改为?使用这种方法有优势吗

我在上找到了这个问题,我在同一篇文章中分享了它的答案

在java.util.Collections JavaDoc中,您可以看到“当用户在返回的列表上进行迭代时,必须手动同步该列表:”

如果您在一个列表上执行多个事务(例如在列表上进行迭代),则同步列表不会保护您免受
ConcurrentModificationException
的影响。当您在列表中进行迭代时,仍然有可能有人将添加或删除到列表中,这将抛出

Collections.synchronizedList()
保护列表不受多线程并发操作的影响。对于迭代器,您正在进行列表调用,但随后返回到代码,然后再次进行列表调用。即使这些方法是同步的,您也不会受到同时在列表上运行的其他线程的争用条件的保护

使用同步的ArrayList会导致额外的工作,为什么不使用java.util.Vector呢?使用这种方法有优势吗

Vector
在这里没有帮助。在相同的情况下,它也会抛出一个异常。引用javadocs:

Vector的迭代器和listIterator方法返回的迭代器故障快速:如果在迭代器创建后的任何时间以任何方式(除迭代器自己的remove或add方法外)修改向量的结构,迭代器将抛出ConcurrentModificationException

另外,
Vector
是一个非常古老的类。人们普遍认为最好使用同步的
ArrayList

以下是您可以做的几件事:

  • 您可以将列表复制到另一个集合中,然后可以在其中进行迭代。即使其他线程从同步列表中添加或删除,您的本地集合也是安全的。当然,这并不能防止您修改列表中的元素
  • 您可以切换到一个完全并发的集合,例如
    ConcurrentHashMap
    (当然它不是一个列表),它在迭代时处理对集合的修改
    ConcurrentSkipList
    LinkedBlockingQueue
    是其他选择
  • 正如@Geek指出的,这是另一种选择,尽管性能在很大程度上取决于迭代和写入的比率

IMHO认为施工不起作用一直是显而易见的。我想知道(事实上,我小时候第一次看到它时就想知道:-)为什么Java工程师设计了Vector。当时没有清晰的记忆模型,所以我不确定同步是否有任何好处。@BorisTreukhov好处是互斥。@MarkoTopolnik事实上,事实证明矢量没有替代品-因此它与-synchronization name
Vector
,无关,与
哈希表
的情况相同<代码>数组列表和
哈希映射
被添加到JDK1中。2@BorisTreukhov这是众所周知的。我以为您想知道为什么Java的原始集合是同步的。根据遍历与写入操作的比率,在这里可能很有用。
synchronized(list) {
    Iterator i = list.iterator(); // Must be in synchronized block
    while (i.hasNext())
    foo(i.next());
}