Aina Eguchi
Aina Eguchi

Reputation: 3

Getting ConcurrentModificationException despite using synchronized to sort a Collection

I tried to sort the collection using threaded methods where the methods call comparator classes individually

public class ThreadedSort{
   public ThreadedSort(){
       ThreadedIDSort idSort=new ThreadedIDSort();
       ThreadedNameSort nameSort=new ThreadedNameSort();
       ThreadedSalarySort salarySort=new ThreadedSalarySort();

        ExecutorService threadExecutor=Executors.newCachedThreadPool();

        threadExecutor.execute(idSort);
        threadExecutor.execute(nameSort);
        threadExecutor.execute(salarySort);

   }
}

Each threaded method looks like this:

public class ThreadedIDSort implements Runnable, EmployeeInterface {
    public synchronized void run(){
        employeeList.sort(new IDComparator());
    }
  }

The ID Compartator class is as follows:

public class IDComparator implements Comparator<Employee> {
    @Override
    public int compare(Employee a, Employee b) {
        return a.getID()-b.getID();
    }

}

The employeeList is a list of objects having attributes name, id, salary and post:

ArrayList<Employee> employeeList=new ArrayList<>();

Though I added synchronized before run method, editing the list still gives ConcurrentModificationException

Exception in thread "pool-2-thread-2" Exception in thread "JavaFX Application Thread" java.util.ConcurrentModificationException
    at java.base/java.util.ArrayList.sort(ArrayList.java:1723)
    at Client.Sort.Threaded.ThreadedNameSort.run(ThreadedNameSort.java:9)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at java.base/java.lang.Thread.run(Thread.java:831)

I am trying to sort using name, post and ID all at once using threads.

Upvotes: 0

Views: 119

Answers (3)

kus
kus

Reputation: 504

The issue is with same 'employeeList' being modified by concurrently running different threads.

One of the options is to clone the employeeList and assign separate list for sorting.

Example:

ArrayList<Employee> employeeList=new ArrayList<>();

ArrayList<Employee>  employeeListByName = employeeList.clone();

ArrayList<Employee>  employeeListBySalary = employeeList.clone();

// use copy of list in respective thread

ThreadedIDSort  -> use employeeList
ThreadedNameSort -> use employeeListByName
ThreadedSalarySort -> use employeeListBySalary

Upvotes: 0

Solomon Slow
Solomon Slow

Reputation: 27145

Rob Spoor explained why ConcurrentModificationException isn't necessarily about threading. But also, you should know this:

The synchronized keyword on the run() method in your example has no effect.

When you write a synchronized method,

    public synchronized void bar() {
        ...
    }

That's the same as if you wrote,

    public void bar() {
        synchronized(this) {
             ...
        }
    }

In your example, each of the three tasks that you submit to the executor service is a different Runnable object. The keyword, this, refers to a different object in each of the three run() methods. Three different threads synchronizing on three different objects is the same as no synchronization at all.

Synchronization is only meaningful when the threads synchronize on the same object. The rule is, no two threads will ever be allowed to synchronize on the same object at the same time.

Upvotes: 1

Rob Spoor
Rob Spoor

Reputation: 9135

A ConcurrentModification can also occur in single threaded applications. They occur when a collection is both modified and iterated over. That can be as simple as the following:

for (String s : myStringList) {
    if ("X".equals(s)) {
        myStringList.remove(s);
    }
}

Note that the so-called concurrent collections, from java.util.concurrent, have been designed to support this, but most (all?) from java.util have the same issue, even if you apply synchronisation.

Without seeing what employeeList is exactly, and what IDComparator does, it's difficult to say why the exception is thrown in this specific case.

Upvotes: 0

Related Questions