Why Isn't This Code Causing a Concurrentmodificationexception

Why isn't this code causing a ConcurrentModificationException?

According to the Java API docs Iterator.hasNext does not throw a ConcurrentModificationException.

After checking "January" and "February" you remove one element from the list. Calling it.hasNext() does not throw a ConcurrentModificationException but returns false. Thus your code exits cleanly. The last String however is never checked. If you add "April" to the list you get the Exception as expected.

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

public class Main {
public static void main(String args[]) {

List<String> myList = new ArrayList<String>();
myList.add("January");
myList.add("February");
myList.add("March");
myList.add("April");

Iterator<String> it = myList.iterator();
while(it.hasNext())
{
String item = it.next();
System.out.println("Checking: " + item);
if("February".equals(item))
{
myList.remove(item);
}
}

for (String item : myList)
{
System.out.println(item);
}

}
}

http://ideone.com/VKhHWN

java.util.ConcurrentModificationException not thrown when expected

The iterator returned from ArrayList.iterator() in the implementation we're apparently both using only checks for structural modification in calls to next(), not in calls to hasNext(). The latter just looks like this (under Java 8):

public boolean hasNext() {
return cursor != size;
}

So in your second case, the iterator "knows" that it's returned two elements, and that the list only has two elements... so hasNext() just returns false, and we never end up calling next() the third time.

I would view this as an implementation detail - basically the checking not being as strict as it could be. It would be entirely reasonable for hasNext() to perform a check and throw an exception in this case too.

For java List concurrent modification exception not thrown if remove method invoked before iteration

Look at ArrayList.Itr.

There're two counters: ArrayList.modCount and ArrayList.Itr.expectedModCount. ArrayList.Itr throws ConcurrentModificationException when modCount != expectedModCount.

This is correct. But if you look at ArrayList.Itr.hasNext you can see:

public boolean hasNext() {
return cursor != size;
}

When you remove one element and you list become empty, then your code does not invoke it.next().

To make your code throw ConcurrentModificationException, you should have not empty list before while loop:

public static void main(String[] args)
{
List<String> l1 = new ArrayList<>();
l1.add("v1");
l1.add("v2");
Iterator<String> it = l1.iterator();
l1.remove(0);
while(it.hasNext()) {
System.out.println(it.next()); // --> ConcurrentModificationException
}
}

Why does this code cause a ConcurrentModificationException in Java?

I'm assuming you're rendering something to screen in the code.frame.GameEngine.render() method. The problem is you're using a LinkedList which is not thread-safe. Thus, it's possible to add a new GUIElement to elements while code.frame.GameEngine.render() method is iterating over elements (this happens asynchronously). You need to use a thread-safe collection like:

List<GUIElement> elements = Collections.synchronizedList(new LinkedList<GUIElement>());

Java ConcurrentModificationException

I'm seeing the same thing,

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Launcher
{
public static void main(String[] args)
{
doThis();
doThat();
}

private static void doThis()
{
System.out.println("dothis");
try
{
List<String> myList1 = new ArrayList<String>();
Collections.addAll(myList1, "str1","str2","str3","str4","str5");
for(String element : myList1){//no ConcurrentModificationException here
if(element.equalsIgnoreCase("str4"))
myList1.remove("str4");
}
System.out.println(myList1);
}
catch(Exception e)
{
e.printStackTrace();
}
}

private static void doThat()
{
System.out.println("dothat");
try
{
List<String> myList2 = new ArrayList<String>();
Collections.addAll(myList2, "str1","str2","str3","str4","str5");
for(String element : myList2){//ConcurrentModificationException here
if(element.equalsIgnoreCase("str1"))
myList2.remove("str1");
}
System.out.println(myList2);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}

which outputs,

dothis
[str1, str2, str3, str5]
dothat
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at com.foo.Launcher.doThat(Launcher.java:41)
at com.foo.Launcher.main(Launcher.java:12)

And I've found the reason.

ConcurrentModificationException: Why does removing the null in List throw this Exception if it´s not the first variable

Well, in a best case scenario, the ConcurrentModificationException should be thrown in any of the two cases. But it isn't (see the quote from the docs below).

If you use the for-each loop to iterate over an Iterable, the Iterator returned by the iterator() method of the data structure will be used internally (the for-each loop is just syntactic sugar).

Now you shouldn't (structurally) modify an Iterable that is being iterated after this Iterator instance was created (it's illegal unless you use the Iterator's remove() method). This is what a concurrent modification is: There are two different perspectives on the same data structure. If it's modified from one perspective (list.remove(object)), the other perspective (the Iterator) won't be aware of this.

It is not about the element being null. The same happens if you change the code to remove the string:

ArrayList<Object> s = new ArrayList<>();

s.add("test");
s.add(null);

try {
System.out.println(s + "\n");
for (Object t : s) {
System.out.println(t);

if (t != null && t.equals("test")) {
s.remove(t);
System.out.println("ObjectRemoved = " + t + "\n");
}

}

System.out.println(s + "\n");
} catch (ConcurrentModificationException e) {
System.out.println(e);
} catch (Exception e) {
System.out.println(e);
}

Now the reason this behaviour differs in some scenarios is simply the following (from the Java SE 11 Docs for ArrayList):

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list 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. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

Getting concurrent modification exception while using iterator in multithreaded program

Java's ArrayList isn't thread safe, regardless of whether you use an iterator.

From the Javadoc:

If multiple threads access an ArrayList instance concurrently, and at
least one of the threads modifies the list structurally, it must be
synchronized externally.

...

The iterators returned by this class's iterator and listIterator
methods are fail-fast: if the list 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

Take a look at this question for a discussion of thread-safe alternatives. Basically, you'll need to either use locks (such as synchronized blocks), or a suitable thread-safe list.



Related Topics



Leave a reply



Submit