title: Android: How to correctly synchronize iteration over Set when another thread can remove elements from the Set?
body: <p>Why does a call to <code>removeListener()</code> in the following code throw a <code>ConcurrentModificationException</code> when another thread is using the iterator in <code>fireEvent()</code>?</p>
  
  <pre><code>public class MyClass {
  
      private Set&lt;Object&gt; synchronizedListeners;
  
      public MyClass() {
          synchronizedListeners = Collections.synchronizedSet(
                  new LinkedHashSet&lt;Object&gt;());
      }
  
      public void addListener(Object listener) {
          synchronizedListeners.add(listener);
      }
  
      public synchronized void removeListener(Object listener) {
          synchronizedListeners.remove(listener);
      }
  
      public void fireEvent() {
          synchronized (synchronizedListeners) {
              for (Object listener : synchronizedListeners) {
                  // do something with listener
              }
          }
      }
  }
  </code></pre>
  
  <p>From my understanding, since I'm using <code>synchronized (synchronizedListeners)</code> in <code>fireEvent()</code>, this should block any other thread that calls <code>removeListener()</code>, till the iteration in <code>fireEvent()</code> is complete at which point it should be safe to remove an element from this Set. But this doesn't seem to be the case. What am I doing wrong?</p>
  
  <p>Possibly related: <a href="https://stackoverflow.com/questions/567068/java-synchronized-block-vs-collections-synchronizedmap">Java synchronized block vs. Collections.synchronizedMap</a></p>
  
  <p><strong>Edit:</strong> It was pointed out that I was unnecessarily synchronizing the removeListener() method. So I tried this version:</p>
  
  <pre><code>public void removeListener(Object listener) {
      synchronizedListeners.remove(listener);
  }
  </code></pre>
  
  <p>But still got the same error.</p>
  
  <p><strong>Edit 2:</strong> As assylias pointed out, the problem isn't visible in the above code. I was calling <code>removeListener()</code> from inside the for loop in the <code>synchronized (synchronizedListeners)</code> block which was causing the error. The fix I ended up using in this case is to remove the listener from another thread:</p>
  
  <pre><code>public void removeListener(final Object listener) {
      new Thread() {
          @Override
          public void run() {
              synchronizedListeners.remove(listener);
          }
      }.start();
  }
  </code></pre>