title: Iterating a WeakHashMap
body: <p>I'm using a WeakHashMap concurrently. I want to achieve fine-grained locking based on an Integer parameter; if thread A needs to modify a resource identified by Integer <code>a</code> and thread B does the same for resource identified by Integer <code>b</code>, then they need not to be synchronized. However, if there are two threads using the same resource, say thread C is also using a resource identified by Integer <code>a</code>, then of course thread A and C need to synchronize on the same Lock.</p>
  
  <p>When there are no more threads that need the resource with ID X then the Lock in the Map for key=X can be removed. However, another thread can come in at that moment and try to use the lock in the Map for ID=X, so we need global synchronization when adding/removing the lock. (This would be the only place where every thread must synchronize, regardless of the Integer parameter) But, a thread cannot know when to remove the lock, because it doesn't know it is the last thread using the lock.</p>
  
  <p>That's why I'm using a WeakHashMap: when the ID is no longer used, the key-value pair can be removed when the GC wants it.</p>
  
  <p>To make sure I have a strong reference to the key of an already existing entry, and exactly that object reference that forms the key of the mapping, I need to iterate the keySet of the map:</p>
  
  <pre><code>synchronized (mrLocks){
      // ... do other stuff
      for (Integer entryKey : mrLocks.keySet()) {
          if (entryKey.equals(id)) {
              key = entryKey;
              break;
          }
      }
      // if key==null, no thread has a strong reference to the Integer
      // key, so no thread is doing work on resource with id, so we can
      // add a mapping (new Integer(id) =&gt; new ReentrantLock()) here as
      // we are in a synchronized block. We must keep a strong reference
      // to the newly created Integer, because otherwise the id-lock mapping
      // may already have been removed by the time we start using it, and 
      // then other threads will not use the same Lock object for this
      // resource
  }
  </code></pre>
  
  <p>Now, can the content of the Map change while iterating it? I think not, because by calling <code>mrLocks.keySet()</code>, I created a strong reference to all keys for the scope of iteration. Is that correct?</p>