Why does this code raise java ConcurrentModificationException?

public final class ClientGateway {

   private static ClientGateway instance;
   private static List<NetworkClientListener> listeners = Collections.synchronizedList(new ArrayList<NetworkClientListener>());
   private static final Object listenersMutex = new Object();
   protected EventHandler eventHandler;


   private ClientGateway() {
      eventHandler = new EventHandler();
   }

   public static synchronized ClientGateway getInstance() {
      if (instance == null)
         instance = new ClientGateway();
      return instance;
   }

   public void addNetworkListener(NetworkClientListener listener) {
     synchronized (listenersMutex) {
        listeners.add(listener);
     }
   }


   class EventHandler {

     public void onLogin(final boolean isAdviceGiver) {
        new Thread() {
           public void run() {
              synchronized (listenersMutex) {
                 for (NetworkClientListener nl : listeners) 
                    nl.onLogin(isAdviceGiver);
              }
           }
        }.start();
     }

   }
}

This code throws a ConcurrentModificationException, but I thought that if they are both synchronized on listenersMutex, then should they be executed in serial mode? All the code in the functions that work in the list of listeners works in synchronized blocks that are synchronized in Mutex. The only code that modifies the list is addNetworkListener (...) and removeNetworkListener (...), but removeNetworkListener is never called at the moment.

What happens with the error is that the NetworkClientListener is still added when the onLogin function / thread iterates through the listeners.

Thank you for understanding!

EDIT: NetworkClientListener - "onLogin" , , .

, addNetworkListener() removeNetworkListener(), . :

for (NetworkClientListener nl : listeners) 
   nl.onLogin(isAdviceGiver);

To:

for(int i = 0; i < listeners.size(); i++)
   nl.onLogin(isAdviceGiver);

concurrency, , , .

!

: "Thread-5" java.util.ConcurrentModificationException    java.util.ArrayList $Itr.checkForComodification(ArrayList.java:782)    java.util.ArrayList $Itr.next(ArrayList.java:754)    chapchat.client.networkcommunication.ClientGateway $EventHandler $5.run(ClientGateway.java:283)

EDIT , . ! , MJB jprete!

: onLogin() . ( java- Threads , Thread ), onLogin() , , .

MJB CopyOnWriteArrayList

+3
3

. nl.onLogin() , listeners, ConcurrentModificationException, ( ) () .

EDIT: , . , Java , . , , , . , ; , a ConcurrentModificationException , . next(), listeners .

+3

, - removeListeners .

nl.onLogin? , .

, , CopyOnWriteArrayList - - CopyOnWriteArrayList , CME ( , , nl.onLogin).

+2

ArrayList CopyOnWriteArrayList, ConcurrentModificationException, . , (, ), , iterater .

This is a bit slower than an ArrayList. This is useful in cases where you do not want to synchronize iterations.

+1
source

All Articles