Concurrent change detection?

In the multi-threaded application I'm working on, we sometimes see ConcurrentModificationExceptions on our lists (mostly an ArrayList , sometimes Vectors). But there are other cases where I think that simultaneous changes occur because repetition through the collection seems to be an absent element, but no exceptions are thrown. I know that the docs for ConcurrentModificationException say that you cannot rely on it, but how can I make sure that I don't change the List at the same time? And does each access to the collection in the synchronized block complete the only way to prevent this?

Update: Yes, I know about Collections.synchronizedCollection , but it does not protect someone modifying the collection when you iterate through it. I think that at least some of my problems happen when someone adds something to the collection while I repeat it.

Second update . If someone wants to combine the mention of synchronizedCollection and cloning, as Jason did with the mention of java.util.concurrent and apache frameworks like jacekfoo and Javamann, I can accept the answer.

+7
java collections
source share
12 answers

Your initial question seems to require an iterator that sees live updates to the base collection while remaining in streaming mode. This is an extremely costly problem to solve in the general case, so none of the standard collection classes do this.

There are many ways to solve partial solutions to a problem, and in your application one of them may be sufficient.

Jason provides a concrete way to ensure thread safety and avoid throwing a ConcurrentModificationException , but only at the cost of survivability.

Javamann mentions two specific classes in the java.util.concurrent package that solve the same problem without blocking, where scalability is critical. They ship only with Java 5, but there are various projects that support the package features in earlier versions of Java, including this one , although they will not have such good work in earlier JREs.

If you are already using some Apache Commons libraries, then, as jacekfoo points out, the framework contains several useful classes.

You might also consider browsing the Google Collections framework .

+4
source share

One of my favorites is CopyOnWriteArrayList or CopyOnWriteArraySet, depending on the refresh rate. They create a new list / set of updates to avoid the exception of simultaneous modification.

+6
source share

Check java.util.concurrent for versions of the standard collection classes that are designed to handle concurrency better.

+3
source share

Yes, you need to synchronize access to collection objects.

Alternatively, you can use synchronized wrappers around any existing object. See Collections.synchronizedCollection () . For example:

 List<String> safeList = Collections.synchronizedList( originalList ); 

However, all code must use a secure version, and even then iterating when changing another thread will lead to problems.

To solve the iteration problem, first copy the list. Example:

 for ( String el : safeList.clone() ) { ... } 

For more streamlined, thread safe collections, also see java.util.concurrent .

+3
source share

Usually you get a ConcurrentModificationException if you try to remove an item from the list while it repeats.

The easiest way to verify this:

 List<Blah> list = new ArrayList<Blah>(); for (Blah blah : list) { list.remove(blah); // will throw the exception } 

I'm not sure how you will manage. You may need to implement your own thread-safe list, or you can create copies of the original list for writing and have a synchronized class that is written to the list.

+2
source share

You can try using protective copying so that changes to one List do not affect the others.

+1
source share

Collection workaround in a synchronized block is the right way to do this. Standard programming practice dictates the use of some kind of locking mechanism (semaphore, mutex, etc.) when working with a state that is used for multiple threads.

Depending on your use case, you can do some optimizations only to block in certain cases. For example, if you have a collection that is read frequently but rarely written, you can allow concurrent reads, but force blocking whenever a write occurs. Reading at the same time causes conflicts only if the collection is in the process of being modified.

+1
source share

ConcurrentModificationException is the best effort, because what you are asking is a difficult problem. There is no good way to do this reliably without sacrificing performance, except that your access templates do not change this list at the same time.

Syncing is likely to prevent concurrent changes, and perhaps this is what you are resorting to, but it can be costly. It’s best to probably sit down and think about your algorithm. If you cannot find a solution without blocking, refer to synchronization.

+1
source share

See implementation. It basically stores int:

 transient volatile int modCount; 

and this increases in the presence of a “structural modification” (eg, removal). If the iterator detects that modCount has changed this, it throws a parallel modification exception.

Synchronization (via Collections.synchronizedXXX) will not be useful, since it does not guarantee the security of the iterator, it only synchronizes the records and reads with put, get, set ...

See java.util.concurennt and apache frameworks (it has optimized optimized classes that work correctly in a parallel environment when there is more reading (which are not synchronized) than writing - see FastHashMap.

+1
source share

You can also synchronize iterations over the list.

 List<String> safeList = Collections.synchronizedList( originalList ); public void doSomething() { synchronized(safeList){ for(String s : safeList){ System.out.println(s); } } } 

This blocks the list during synchronization and blocks all threads that try to access the list when you edit or iterate over it. The downside is that you create a bottleneck.

This saves some memory using the .clone () method and can be faster depending on what you do in the iteration ...

+1
source share

Collections.synchronizedList () will display the list nominally thread safe, while java.util.concurrent has more powerful functions.

-one
source share

This will save you from eliminating parallel modifications. I will not talk about efficiency, but;)

 List<Blah> list = fillMyList(); List<Blah> temp = new ArrayList<Blah>(); for (Blah blah : list) { //list.remove(blah); would throw the exception temp.add(blah); } list.removeAll(temp); 
-one
source share

All Articles