Concurrent Modification Exception Cause by Painting? - java

I have been having a lot of trouble with the Concurrent Modification Exception error. With the help of the community I managed to fix my last error, however I think this error is more puzzling.
I am now getting a concurrent modification error while painting, I am worried that this error occurs in the paint function itself. Unlike my last error I am nto removing an entity, in that case I completely understood what was going on just not how to fix it, this error on the other hand I do not understand.
TowerItr = activeTowers.iterator();
while (TowerItr.hasNext()) {
try {
theTower = (ArcherTower) TowerItr.next();
g.drawImage(tower, theTower.y * Map.blockSize, theTower.x * Map.blockSize, this);
} catch (ConcurrentModificationException e) {
}
}
The line that throws the exception is this one:
theTower = (ArcherTower) TowerItr.next();

There are always two sides to a ConcurrentModificationException (CME), and only one side reports the error.
In this case, your code looks perfectly fine. You are looping through the members of the activeTowers.
The stack trace will show you nothing that you don't already know.... you have a CME.
What you need to find out is where you are adding/removing data from the activeTowers collection.
In many cases, there are reasonably easy fixes. A probable fix is to synchronize the access to the activeTowers array in every place it is used. This may be quite hard to do.
Another option is to use a collection from the java.util.concurrent.* package, and to use the toArray(...) methods to get a snapshot of the collection, and then you can iterate that snapshot in your while loop.
// activeTower must be something from java.util.concurrent.*
for (ArcherTower theTower : activeTower.toArray(new ArcherTower[0]) {
g.drawImage(tower, theTower.y * Map.blockSize, theTower.x * Map.blockSize, this);
}
I should add that if you use a java.util.concurrent.* collection, then the iterator() will return a 'stable' iterator too (will not throw CME, and may (or may not) reflect changes in the collection)
Bottom line is that a CME only tells you half the story.... and only your code will tell you the rest....

Carrying on from what our esteemed members have suggested:
1) This error is generally seen when the List is being modified after an Iterator has been extracted.
2) I am looking at your code and it seems alright except this being used in the drawImage() method. This may potentially be altering your List because This has direct access to class members / class variables.
3) This can also happen if multiple threads are accessing the List concurrently. And one of the threads may be trying to alter your List from some other method which share the same instance of the List. I am saying some other method because concurrent read access should not create trouble if multiple threads were accessing this method.
Note: Please all posible code and Stake trace to debug exact problem.

Related

Why does this code get stuck in infinite loop [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 12 days ago.
Improve this question
public void bad() {
final ConcurrentMap<String, Integer> chm = new ConcurrentHashMap<>();
final String key = "1";
chm.computeIfAbsent(key, __ -> {
chm.remove(key);
return 1;
});
}
Of course i understand this looks very silly. It is just a super simplified version of some problematic code i was dealing with. I understand it makes no sense to do this but i am trying to understand the behaviour it causes.
When running this code you get stuck in an infinite loop on line 1107 after invoking http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/concurrent/ConcurrentHashMap.java#l1096
I am finding it very difficult to understand exactly what is happening which is causing this. Same behaviour when done on a seperate thread but waiting
public void bad2() {
final ConcurrentMap<String, Integer> chm = new ConcurrentHashMap<>();
final String key = "1";
Thread worker = new Thread(() -> chm.remove("1"));
chm.computeIfAbsent(key, __ -> {
worker.start();
try {
worker.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
});
}
Why in both cases is it not that chm.remove(key) completes normally returning null and then the value of 1 is set?
Interestingly this was addressed at some point and the first example throws java.lang.IllegalStateException: Recursive update when i ran with java 17.
This is called a 'contract error'. This happens when javadoc explicitly tells you NOT to do thing X, and leaves it at that; it does not specify what happens if you do X, just that you shouldn't do that. In this case, X is 'update the map in your passed-in function', and the javadoc explicitly spells out: DO NOT.
so the computation should be short and simple,
and must not attempt to update any other mappings of this map.
When you perform such a contract error, anything can happen. The spec is clear: Don't. So, if you do, the spec essentially claims the ability to do anything. Hard-crash, whistle a dixie tune from the speakers, you name it.
Hence why the behaviour changed (ordinarily, java does not change its behaviours without quite a big ordeal about breaking compatibility, but here, the spec behaviour has not changed, because the spec merely says 'do not do this, this thing does not perform according to spec if you fail to heed this warning' and 'loop endlessly' and 'throw an exception' are both just 'doing unspecified broken stuff' in this regard.
Okay, but why does it endlessly loop?
Because concurrent hashmap is 'smart' and uses a retry/CAS update model. Instead of acquiring a bunch of stuff, it just tries the operation without doing that, but will then check during/afterwards if it actually succeeded, or if, due to other threads modifying the same map at the same time in the same general area, its write got overwritten or otherwise didn't apply, in which case it'll do it again. In this case, removing the key is essentially 'eliminating a marker', which makes CHM think it updated a thing concurrently with another thing and therefore it should try again. Forever and ever.
That's what the 'cas' in line 1656 in your linked source file (casTabAt) stands for: Compare-And-Set. This is a concurrency primitive that can be a lot faster than locks: "If the current value is X, then set it to Y. Otherwise, do not set it at all. Tell me whether you set it or not" - all that, in one atomic operation, which is speedy because CPUs tend to support it as barebones machine code. No lock acquiry required. The general principle is to check what the current value is, do some bookkeeping, then set the new value, using CAS to ensure that the 'state' you checked is still the state we're in. If not, some other thread so happened to also be updating stuff, so, start over.
That's just one implementation. Tomorrow, it can change. You cannot rely on 'it will endlessly loop' because the spec do not guarantee it, and indeed, in JDK17, you get an exception instead.

ConcurrentModificationException coming for CopyOnWriteArrayList as well [duplicate]

I'm occasionally getting a ConcurrentModificationException when I iterate over a list. A Google search informs me that it's probably because I'm altering that list in another thread while iterating over it and that to make this problem go away I should use java.util.concurrent.CopyOnWriteArrayList....
... except I already am.
Apparently, I'm doing something really stupid somewhere.
Does anybody have any insight into how one might induce CopyOnWriteArrayList to toss a ConcurrentModificationException? If it matters, I'm using Java 5.
Edit: Since the mutators I'm using may matter, I'm modifying this list in two ways:
Adding elements to the front. (list.add(0, newElement);)
Using subList to let older items fall off the back. (list = list.subList(0, MAX_LIST_SIZE);)
Do those raise red flags? If so, why? My understanding was that because these operations make a copy of the thing first, any existing iterators would be pointing at the unmodified original and would thus not care. Do I have a hole in my knowledge?
Edit 2: The precise code that's causing the problem is still a bit murky, but I can at least post the exception I'm seeing:
java.util.ConcurrentModificationException
at java.util.concurrent.CopyOnWriteArrayList$COWSubList.checkForComodification(Unknown Source)
at java.util.concurrent.CopyOnWriteArrayList$COWSubList.iterator(Unknown Source)
at....
... where it points to a for-each loop instantiation in my code.
That COWSubList does seem to imply that my call to subList is the root of my problem; I'd still like to understand why.
Edit 3: *facepalm*
CopyOnWriteArrayList.subList() returns a List, not a CopyOnWriteArrayList. The list it returns is under no implied obligation to provide any of COWAL's protections. Which makes using subList() like this to remove elements a Very Bad Idea.
Don't know for certain if this is my culprit, but it's damned suspicious and needs to be corrected regardless.
CopyOnWriteArrayList.subLists throw ConcurrentModificationExceptions if the containing list changes out from underneath it:
public class ListTest {
private static List<int[]> intList;
public static void main (String[] args) {
CopyOnWriteArrayList<Integer> cowal = new CopyOnWriteArrayList<Integer>();
cowal.add(1);
cowal.add(2);
cowal.add(3);
List<Integer> sub = cowal.subList(1, 2);
cowal.add(4);
sub.get(0); //throws ConcurrentModificationException
}
}
Sbodd has the correct answer, but it sounds like using CopyOnWriteArrayList instead of ArrayList is just an attempt to mask the error. The true problem is an attempt to modify the underlying list while iterating over it. You need to find where in your code you are accessing it as such and remove that usage or work around it.

strange error in android java.util.ConcurrentModificationException

Hi guys I have a small problem. I'm writing a app for android and I have a part of my code like this.
public void loop(){
for(Car car:carList)
car.run();
}
I got the error java.util.ConcurrentModificationException
I also tried using iterators in order to solve the problem quickly.
Also, I use synchronized since I checked the error in oracle docs and it says that could be caused by many threads using the same code.
public synchronized void loop(){
Iterator<Car> carIterator = carList.iterator();
while(cardIterator.hasNext()){
carIterator.next().run();
}
}
I don't really know why any of the solutions I found didn't work. I use this portion of code most of the cases in a background service and I use it's class that contains that method (using singleton) in the acivity too.
Thanks in advance to all the comunity
Thanks for the support guys,
-carList is a ArrayList of Car objects.
my car class is like this
public class Car{
private int mSpeed;
private int mDistance; //zero at first
........
public void run(){
mSpeed=getRandomSpeed();
mDistance+=mSpeed;
updateDistanceInDB();//here I sabe the distance in DB using a DB helper
}
.........
}
-The error indicates that it's generated in the line that executes the method run
There's something strange because the app works well in another device I have.
The most brute-force way to fix this exception is to use a CopyOnWriteArrayList in place of your current List. This will ensure that any updates to the list during a for-each loop won't be seen during iteration, and therefore won't throw a ConcurrentModificationException.
According to its documentation:
The "snapshot" style iterator method uses a reference to the state of the array at the point that the iterator was created. This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException.
However, there may be a better way to solve your issue depending on the situation. Look for what parts of your code make modifications to the List, and ensure that they don't run during iteration.

I get the following exception: "java.util.ConcurrentModificationException"

I'm getting a "An exception occurred: java.util.ConcurrentModificationException" when I run this piece of code. Does anyone here see what the problem is?
public void mudaDeEstado() {
Luz luz = new Luz();
while(this.iterador.hasNext()) {
luz = (this.iterador.next());
luz.defineEstado(!luz.acesa());
}
}
Thanks a lot!!
You are trying to modify the reference that the iterator holds while looping through the elements. You can read more about his exception here.
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.
Most probably the culprit here is this:
luz.defineEstado(!luz.acesa());
This exception is thrown when you modify a data structure while you are iterating through it. Changing the elements in the data structure can change the way one iterates through the elements, so many data structures do not allow concurrent modification.
Try keeping a list of elements that need to be updated and then go back through and update those elements once you have iterated through the entire data structure.
Sorry my wording is kind of general and ambiguous, but it's hard to give specifics with the provided code.

CopyOnWriteArrayList throwing CurrentModificationException

I'm occasionally getting a ConcurrentModificationException when I iterate over a list. A Google search informs me that it's probably because I'm altering that list in another thread while iterating over it and that to make this problem go away I should use java.util.concurrent.CopyOnWriteArrayList....
... except I already am.
Apparently, I'm doing something really stupid somewhere.
Does anybody have any insight into how one might induce CopyOnWriteArrayList to toss a ConcurrentModificationException? If it matters, I'm using Java 5.
Edit: Since the mutators I'm using may matter, I'm modifying this list in two ways:
Adding elements to the front. (list.add(0, newElement);)
Using subList to let older items fall off the back. (list = list.subList(0, MAX_LIST_SIZE);)
Do those raise red flags? If so, why? My understanding was that because these operations make a copy of the thing first, any existing iterators would be pointing at the unmodified original and would thus not care. Do I have a hole in my knowledge?
Edit 2: The precise code that's causing the problem is still a bit murky, but I can at least post the exception I'm seeing:
java.util.ConcurrentModificationException
at java.util.concurrent.CopyOnWriteArrayList$COWSubList.checkForComodification(Unknown Source)
at java.util.concurrent.CopyOnWriteArrayList$COWSubList.iterator(Unknown Source)
at....
... where it points to a for-each loop instantiation in my code.
That COWSubList does seem to imply that my call to subList is the root of my problem; I'd still like to understand why.
Edit 3: *facepalm*
CopyOnWriteArrayList.subList() returns a List, not a CopyOnWriteArrayList. The list it returns is under no implied obligation to provide any of COWAL's protections. Which makes using subList() like this to remove elements a Very Bad Idea.
Don't know for certain if this is my culprit, but it's damned suspicious and needs to be corrected regardless.
CopyOnWriteArrayList.subLists throw ConcurrentModificationExceptions if the containing list changes out from underneath it:
public class ListTest {
private static List<int[]> intList;
public static void main (String[] args) {
CopyOnWriteArrayList<Integer> cowal = new CopyOnWriteArrayList<Integer>();
cowal.add(1);
cowal.add(2);
cowal.add(3);
List<Integer> sub = cowal.subList(1, 2);
cowal.add(4);
sub.get(0); //throws ConcurrentModificationException
}
}
Sbodd has the correct answer, but it sounds like using CopyOnWriteArrayList instead of ArrayList is just an attempt to mask the error. The true problem is an attempt to modify the underlying list while iterating over it. You need to find where in your code you are accessing it as such and remove that usage or work around it.

Categories

Resources