Java - synchronized ArrayList still ConcurrentModificationException - java

I got an final ArrayList<RoutingTableEntry> routingTable = new ArrayList<>(); which is accessed multiple times.
But I only get at one Point an ConcurrentModificationException which is in the following Thread:
Thread checkReplies = new Thread(() -> {
while (true) {
synchronized (routingTable) {
for (RoutingTableEntry entry : routingTable) { // throws it here
// do smth
}
}
// [...]
}
});
checkReplies.start();
It throws the exception at the loop even though the routingTable is already synchronized. This thread gets only executed once per class.
Any ideas?

There are two possibilities:
You have other code in the class that modifies routingTable, and doesn't use synchronized (routingTable) when doing so. So when the other code modifies the list during that iteration, you get the error.
You're modifying the list where you have the comment "do smth". Just because you have have the list synchronized, that doesn't mean you can modify it while looping through with its iterator. You can't (except through the iterator itself, which would mean you couldn't use the enhanced for loop). (Sometimes you get away with it because of the details of the ArrayList implementation, but other times you don't.)
Here's an example of #2 (live copy):
var routingTable = new ArrayList<String>();
routingTable.add("one");
routingTable.add("two");
routingTable.add("three");
synchronized (routingTable) {
for (String entry : routingTable) {
if (entry.equals("two")) {
routingTable.add("four");
}
}
}
That fails with JDK12's implementation of ArrayList (at least, probably others).
One key thing to understand is that synchronization and modifying the list during iteration are largely unrelated concepts. Synchronization (done properly) prevents multiple threads from accessing the list at the same time. But as you can see in the example above, just a single thread can cause a ConcurrentModificationException by modifying the list during the iteration. They only relate in that if you have one thread reading the list and another thread that may modify it, synchronization prevents the modification while the read is happening. Other than that, they're unrelated.
In a comment you've said:
i call a method which removes then
If you're removing the entry for the loop, you can do that via a list iterator's remove method:
for (var it = routingTable.listIterator(); it.hasNext; ) {
var entry = it.next();
if (/*...some condition...*/) {
it.remove(); // Removes the current entry
}
}
(There are also add and set operations.)

ConcurrentModificationException is not necessarily 'concurrent' in the sense of threading, it can be 'concurrent' in the sense of that you shall not directly modify a collection at the same time when you are iterating over it.
It is in the docs too, for a long time (excerpt from Java7: https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html)
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
And for(x:y) uses an iterator, which can easily end up being a 'fail-fast' one.

Starting from your comment in the original question, you are removing items in the routingTable while you are iterating.
You can't do it (also if the routingTable is synchronized)
for (RoutingTableEntry entry : routingTable) { // throws it here
// routingTable.remove(....);
}

Related

Java - Concurrent Modification Exception

I am getting a concurrent modification exception on the following code:
for(Iterator<Tile> iter = spawner.activeTiles.iterator(); iter.hasNext();) {
Tile tile = iter.next();
canvas.drawRect(tile, tile.getColor());
}
I understand that concurrent modification happens when it is changed while it is iterating(adding/removing inside of the iteration). I also understand that they can happen when multithreading which is where I think my problem is.
In my game I have a few timers that run on threads. I have a spawner, which adds values to activeTiles on each tick. I then have a 2 timers, one for fading in and one for fading out. Without giving away my game, the tile is basically removed from the list when the fade out has finished, or when the player taps the tile. So there are a few instances where the tiles are removed from the list of tiles:
for(Iterator<Tile> iter = spawner.activeTiles.iterator(); iter.hasNext();) {
Tile tile = iter.next();
if(tile.contains(x, y) && tile.equals(spawner.activeTiles.get(0))) {
vibrator.vibrate(50);
tile.setBroken(true);
score ++;
spawner.setTileDelayInfo();
iter.remove();
and before each new spawn, it removes all of the failed tiles:
private void removeFailedTiles() {
for(Iterator<Tile> iter = activeTiles.iterator(); iter.hasNext();) {
Tile tile = iter.next();
if(tile.isFailed()) {
iter.remove();
}
}
}
It almost seems to happen randomly. So I think it has to do something with timing, but I am new to this kind of exception and don't really know what to look for or why this is happening.
The good news: you nailed the root cause of the problem in your question - you can't have multiple threads accessing a list at the same time unless they're all just reading.
You can address this in one of two ways, depending on how the rest of your code operates. The most 'correct' way is steffen's answer: any list access should be guarded with a synchronized block, and that includes holding the lock for the full duration of any list iterations. Note that if you do this, you want to do as little work as possible while holding the lock - in particular, it's a bad idea to do any sort of listener callbacks while holding a lock.
Your second option is to use a CopyOnWriteArrayList, which is thread-safe and doesn't require any external synchronization - but any modifications to the list (add/remove/replace calls) become significantly more expensive.
Multithreading can be a source of ConcurrentModificationExceptions. It can happen when one thread is modifying the structure of the collection while another thread has an Iterator iterating over it. This can lead to unexpected states in your application when the state of the collection changes when a section of code needs a consistent view of the data. This is needed when you're iterating over a collection of Tiles.
You need to syncrhonize access to the activeTiles collection. Anything that modifies this collection structurally (add or remove), or iterates over it, must synchronize on this collection.
Add a synchronized (activeTiles) block around all code that iterates or structuraly modifies activeTiles. This includes all 3 code snippets you've provided here.
Alternatively, you can make the 3 methods corresponding to your code snippets synchronized.
Either way, no other Thread can execute any of the synchronized blocks until another Thread is finished with its syncrhonized section, preventing the ConcurrentModificationException.
It's not safe to remove elements with an Iterator that supports element-removal, when you're iterating the collection in another thread.
Acquire a Lock in all threads on activeTiles before iterating them.
You might want to make your list thread-safe. Use Collections.synchronizedList().
threadSafeActiveTiles = Collections.synchronizedList(activeTiles);
Mind that you must synchronize on that list when iterating over it:
synchronized (threadSafeActiveTiles) {
for (Iterator<Tile> it = threadSafeActiveTiles.iterator(); it.hasNext();) {
Tile tile = it.next();
// ...
}
}
You then can safely have multiple threads modifying the list, which seems to be your case.
The list returned by Collections.synchronizedList() saves you from having to use the synchronized block (above) in single operations on that list, like add(e), size(), get(i) and so on...

JAVA java.util.ConcurrentModificationException

I am trying to create simple JAVA program. But since last day, I am having this issue, I cannot fix.
public void receiveUpdate(ArrayList<Connection> connections) {
for(Connection senderConnection : connections) {
for(Connection receiverConnection : this.connections) {
if(senderConnection.getDestination() == receiverConnection.getDestination()) {
if(senderConnection.getDistance() + 1 < receiverConnection.getDistance()) {
senderConnection.setEnabled(false);
senderConnection.setDistance(senderConnection.getDistance() + 1);
this.connections.remove(receiverConnection);
this.connections.add(senderConnection);
}
}
}
senderConnection.setEnabled(false);
senderConnection.setDistance(senderConnection.getDistance() + 1);
this.connections.add(senderConnection);
}
}
In this method I always get error:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at router.Router.receiveUpdate(Router.java:56)
at router.Router.sendUpdate(Router.java:49)
at loader.Loader.notifyNetworkChanges(Loader.java:61)
at loader.Loader.main(Loader.java:102)
I have noticed, that exception doesn't appear if I comment block:
senderConnection.setEnabled(false);
senderConnection.setDistance(senderConnection.getDistance() + 1);
this.connections.add(senderConnection);
Can anyone tell me, where is the problem?
ConcurrentModificationException This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.
The problem is here
this.connections.remove(receiverConnection);
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.
For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
Check this out
To solve your problem you need to use Iterator and remove() method like this
Iterator<String> connectionsIterator = connections.iterator();
while (connectionsIterator.hasNext()) {
if (senderConnection.getDistance() + 1 < receiverConnection.getDistance()){
connectionsIterator.remove();
// add the connection to another list other than this.connections.add(senderConnection);
// then when you finish add them back the this.connections
// so you avoid modifying this.connections
}
}
You are actually modifying the collections, while iterating.
this.connections.remove(receiverConnection);
this.connections.add(senderConnection);
Use an Iterator and call remove():
Iterator<String> iter = connections.iterator();
while (iter.hasNext()) {
if (someCondition)
iter.remove();
}
Use Iterator remove method instead of ArrayList
If you are modifying (eg deleting from) the same list you are looping then you are bound to get the ConcurrentModificationException
You can either use an iterator as #ankur-singhal mentioned or make a deep copy of the list and remove from that copy. Then you can assign the reference of the original list to point to the new one that has the modifications.
Another "greedy" approach (but without using iterators) would be to keep all items to be removed in another new list and after ending your for loop then call removeAll(listOfConnectionsToBeRemoved), for example:
before your for loops
ArrayList<Connection> connectionsToBeRemoved = new ArrayList<Connection>();
inside your for loops
connectionsToBeRemoved.add(receiverConnection)
after ending your for loops
this.connections.removeAll(connectionsToBeRemoved)
*you may do the same for connections to be added. Keep them in a new list and then add them all to your connection list.
You are looping through this.connections and inside you are trying to remove from this.connections this will java.util.ConcurrentModificationException. Change your code to use iterator.

java.util.ConcurrentModificationException upon LinkedHashSet iteration

Please, help me understand the error I am getting:
private void replayHistory() {
synchronized (alarmsHistory) {
for (AlarmEvent alarmEvent : alarmsHistory) {
LOG.error("replayHistory " + alarmEvent.type + " " + alarmEvent.source);
sendNotification(alarmEvent.type, alarmEvent.source, alarmEvent.description,
alarmEvent.clearOnOtherStations, alarmEvent.forceClearOnOtherStations);
}
}
}
and the method that adds an element to it
private void addToAlarmsHistory(AlarmEvent alarmEvent) {
synchronized (alarmsHistory) {
LOG.error("addToAlarmsHistory " + alarmEvent.type + " " + alarmEvent.source);
alarmsHistory.add(alarmEvent);
}
}
both methods and the Set
private volatile Set<AlarmEvent> alarmsHistory = new LinkedHashSet<AlarmEvent>();
are defined in
JmxGwReloadThread extends Thread class
which is an inner class in
AlarmManager class
that has a method
private void addToReplayHistory(AlarmEvent alarmEvent) {
if ((jmxThread != null) && (jmxThread.isAlive())) {
jmxThread.addToAlarmsHistory(alarmEvent);
}
}
which is being called by different interfaces (cannot assure when and how often)
At some point JmxThread is started and calls replayHistory method
java.util.ConcurrentModificationException is thrown, the root is from the
for (AlarmEvent alarmEvent : alarmsHistory) {
The code propably tries to add an element to the alarmsHistory and when interator
java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:390)
at java.util.LinkedHashMap$KeyIterator.next(LinkedHashMap.java:401)
at AlarmManager$JmxGwReloadThread.replayHistory(AlarmManager.java:568)
at AlarmManager$JmxGwReloadThread.run(AlarmManager.java:532)
throws exception upon calling nextEntry, but should't synchronization prevent from such an issue?
Logs show that synchronization does not work - replayHistory should iterate over all its elements (I can asure its more then one single HEARTBEAT_INFO FM) but it's interrupted by the addToReplayHistory call.
2013-07-11 11:58:33,951 Thread-280 ERROR AlarmManager$JmxGwReloadThread.replayHistory(AlarmManager.java:570) - replayHistory HEARTBEAT_INFO FM
2013-07-11 11:58:33,951 Thread-280 ERROR AlarmManager$JmxGwReloadThread.addToAlarmsHistory(AlarmManager.java:550) - addToAlarmsHistory HEARTBEAT_INFO FM
2013-07-11 11:58:33,952 Thread-280 ERROR Log4jConfigurator$UncaughtExceptionHandler.uncaughtException(Log4jConfigurator.java:253) - Detected uncaught exception in thread: Thread-280
One thing OP (and probably most people) should be aware of:
ConcurrentModificationException has nothing to do with multi-threading.
Although multi-threading makes it much easier to happen, but the core of this problem has nothing to do with multi-threading.
This is mostly caused by scenario like,
Get the iterator from a collection,
Before finish using that iterator, the collection is structurally modified.
Keep on using the iterator after 2. The iterator will detect the collection is structurally modified and will throw out ConcurrentModificationException.
Of course, not all collection have such behavior, e.g. ConcurrentHashMap. Definition of "Structurally Modified" is different for different collection too.
That means, even I have only 1 thread, if I do something like:
List<String> strings = new ArrayList<String>();
//....
for (String s: strings) { // iterating through the collection
strings.add("x"); // structurally modifying the collection
}
I will get ConcurrentModificationException even it is all happening in single thread.
There are different ways to solve the problem, depending on your requirement or problem. e.g.
If it is simply due to multi-thread access, proper synchronize access can be one solution
You may make use of Collection that iterator is safe from structural modification (e.g. ConcurrentHashMap)
Adjust your logic to either re-acquire the iterator again if you modified the collection, or makes your modification using the iterator (some collection impls allows that), or make sure modification to collection happens after you finish using the iterator.
Given that your code seems having proper synchronization on alarmHistory, there are two directions you would want to check
Is there any possible modification of alarmHistory inside sendNotification()? For example, adding or removing from alarmHistory?
Is there other possible unsynchronized access to alarmHistory which may modify the structure?
If one thread iterates, and another thread adds, you're hosed.
Given that your code seems to synchronise access to the two relevant blocks of code, look for other unsynchronized code that adds/removes from alarmsHistory.
The only idea which comes to my head that you have an intricate logic behind the scene. I think the sendNotification somehow recursively invokes addToReplayHistory. So, the multithreading is a red herring, the log file shows only one thread involved, and immideately after sendNotification there is addToReplayHistory call which modifies the collection and breaks the interator.
More info is in the javadoc for the exception:
Note that this exception does not always indicate that an object has
been concurrently modified by a different thread. If a single thread
issues a sequence of method invocations that violates the contract of
an object, the object may throw this exception. For example, if a
thread modifies a collection directly while it is iterating over the
collection with a fail-fast iterator, the iterator will throw this
exception.
To add some details to kan's answer:
The synchronized block in Java is reentrant:
Reentrant SynchronizationRecall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.
So like kan pointed out, it might in fact be that not multiple threads are modifying your collection but only one thread which, due to the reentrant behavior, may always acquire the lock.
The things you should look for to fix the exception are recursive calls between synchronized blocks, or unsychronized access to alarmsHistory.
You can also look into concurrent collections like ConcurrentSkipList or CopyOnWriteArraySet. Both should prevent the exception, but beware of their behavior and performance characteristics described in the JavaDoc.

Problems with ListIterator and Concurrent Modification Exception

I have two ArrayLists, each holding blocks of certain size: blockList, eraserList. Blocks are objects with two fields: start and end. I need to subtract one set of blocks from the other set of blocks.
I must walk through the eraserList and "erase" blocks out of the blockList where they overlap. Thus my code looks like:
void eraseBlocks (Arrylist<Blocks> blockList, ArrayList<Blocks> eraserList) {
ListIterator<Blocks> it = blockList.listIterator();
for (Blocks eraser: eraserList) {
while (it.hasNext()) {
Blocks block= it.next();
if ((eraser.start <= block.start) && (eraser.end >= block.end))
blockList.remove(block);
else if ((eraser.start <= block.start) && (eraser.end < block.end)){
block.set(start, eraser.end);
else if () {
...
//more code for where the eraser partially erases the beginning, end, or splits the block
//if statements call the .add(), .set(), and remove() methods on the blockList.
...
}
}
}
I don't understand why I am getting a Concurrent Modification Exception. I never modify the eraserList.
I am trying to modify the block object that is assigned in the "Block block = it.next();" statement. I am also modifying the blockList by removing or adding blocks to the list. I thought the whole point of the ListIterator was that it allowed you to modify, add, or subtract a list you are walking through.
The Failure Trace points to the Blocks eraser = it.next(); as the line drawing the exception, but I don't know what that is telling me.
Can anyone help me figure out what I am doing wrong?
Thanks!
Yes, ListIterator is designed to allow the modification of the list. But you are not using the remove() method of the ListIterator, but directly manipulate the underlying list itself.
Replace
blockList.remove(block);
with
it.remove();
If you remove an element another way, you can get a CME.
You need to call remove() on the Iterator, not on the List.
From the javadoc:
If a single thread issues a sequence of method invocations that
violates the contract of an object, the object may throw this
exception. For example, if a thread modifies a collection directly
while it is iterating over the collection with a fail-fast iterator,
the iterator will thow this exception.

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.

Categories

Resources