开发者

Concurrent crash using a Vector in Java

I think I'm not understanding correctly what means that a Vector in Java is synchronized. In my code some threads are running instructions that modify my vector, for example calling to mVector.addAll(anothervector). But my application is crashing when interating the vector with following code:

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


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

Why 开发者_开发问答is this crashing if the Vector objects are synchronized? and how can I solve it? Thanks in advance


You didn't specify what you mean by "crashing" but if you're getting a ConcurrentModificationException it means that another thread modified your list while inside of the for-each loop.

This exception doesn't denote a synchronization problem per se as it can be replicated in a single thread (simply try adding an element to the list while iterating over it). Rather it is thrown when the structure of a collection is modified while it is being iterated over. An Iterator is stateful; modifying the collection while it's in use would lead to very bad bugs so the runtime protects against it.

To fix it you could wrap the for-loop in a synchronized block:

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


Read the docs for Vector:

The Iterators returned by Vector's iterator and listIterator methods are fail-fast: if the Vector is structurally modified at any time after the Iterator is created, in any way except through the Iterator's own remove or add methods, the Iterator will throw a ConcurrentModificationException.

The class is thread-safe in the sense that multiple threads can read/add/remove elements at the same time with well-defined behavior.

The iterators are also thread-safe in the sens that they will never return an element that was removed or otherwise invalid.

But that does not mean you can iterate over a vector while modifying it from some other thread.


Vector being synchronized does not mean that, it will save us from misconceptions of synchronization.

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);
    }
  }

}

Above code will simply through ConcurrentModificationException. Reason is, above code is trying to iterate through a collection by this time it is trying to update itself. It is not possible that we can do simultaneously.

If you need to achieve something like this, mark/store the elements somehow (eg: in a list) and update the vector (also any collection) after you are done with the iteration.

EDIT

Make sure that printVector() method is (not) called inside a foreach block of mVector to get rid of ConcurrentModificationException.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜