使用Java中的Vector同时崩溃

时间:2011-08-21 06:44:34

标签: java multithreading thread-safety

我认为我不能正确理解Java中的Vector是如何同步的。 在我的代码中,一些线程正在运行修改我的向量的指令,例如调用mVector.addAll(anothervector)。但是在使用以下代码对向量进行交互时,我的应用程序崩溃了:

// the vector declaration
Vector<myClass> mVector = new Vector<myClass>;


// the method that crashes
public void printVector(){
    for (myClass mObject: mVector){
       System.out.println(mObject); 
    }
 }

如果Vector对象同步,为什么会崩溃?我该如何解决?提前致谢

3 个答案:

答案 0 :(得分:6)

您没有指定“崩溃”的含义,但是如果您获得ConcurrentModificationException,则表示另一个线程在for-each循环内部修改了您的列表。

此异常不表示同步问题本身,因为它可以在单个线程中复制(只需尝试在迭代时向列表中添加元素)。而是在迭代过程中修改集合的结构时抛出它。 Iterator是有状态的;在使用它时修改集合会导致非常糟糕的错误,因此运行时可以防止它。

要修复它,你可以将for循环包装在synchronized块中:

synchronized (mVector) {
    for (... ) {
    }
}

答案 1 :(得分:2)

阅读Vector的文档:

  

Vector的iterator和listIterator方法返回的迭代器是快速失败的:如果在创建Iterator之后的任何时候对Vector进行结构修改,除了通过Iterator自己的remove或add方法之外,Iterator将抛出一个ConcurrentModificationException的。

该类是线程安全的,因为多个线程可以使用明确定义的行为同时读取/添加/删除元素。

迭代器线程安全,因为它们永远不会返回被删除或无效的元素。

但这并不意味着你可以在从某个其他线程修改它时迭代一个向量。

答案 2 :(得分:0)

正在同步的矢量并不意味着,它将使我们免于对同步的误解。

import java.util.List;
import java.util.Vector;

public class Main {

  public static void main(final String[] args) {
    List<Integer> integers = new Vector<Integer>();
    for (int i = 0; i < 10; i++) {
      integers.add(i);
    }
    for (Integer integer : integers) {
      integers.add(1); // this will raise ConcurrentModificationException
      System.out.println(integer);
    }
  }

}

以上代码只会通过ConcurrentModificationException。原因是,上面的代码试图迭代一个集合,此时它正试图更新自己。我们不可能同时做到。

如果你需要实现这样的东西,那么以某种方式标记/存储元素(例如:在列表中)并在完成迭代后更新向量(也是任何集合)。

修改

确保在printVector()的foreach块内调用(非)mVector方法,以摆脱ConcurrentModificationException