title: Implementing blocking concurrency using ReentrantLock
body: <p>I am attempting to implement a class to enforce concurrency in my java application by blocking asynchronous attempts to a modify a given instance of an entity (identified by a key) using RentrantLock.  The goal is to block/queue multiple concurrent attempts to modify a given instance of an object until previous threads have completed.  The class implements this in a generic way, allowing any block of code to obtain a lock and release it once done (identical to the RentrantLock semantics) with the added utility of only blocking threads attempting to modify the same instance of the object (as identified by a key) rather than blocking all threads entering the block of code.</p>
  
  <p>This class provides a simple construct to allow synchronizing a block of code just for one instance of an entity. For example if I want a block of code to be synchronized for all threads coming from user with id 33, but i don't want threads from any other user blocked by the thread servicing user 33.</p>
  
  <p>The class is implemented as follows</p>
  
  <pre><code>public class EntitySynchronizer {
    private static final int DEFAULT_MAXIMUM_LOCK_DURATION_SECONDS = 300; // 5 minutes
    private Object mutex = new Object();
    private ConcurrentHashMap&lt;Object, ReentrantLock&gt; locks = new ConcurrentHashMap&lt;Object, ReentrantLock&gt;();
    private static ThreadLocal&lt;Object&gt; keyThreadLocal = new ThreadLocal&lt;Object&gt;();
    private int maximumLockDurationSeconds;
    public EntitySynchronizer() {
      this(DEFAULT_MAXIMUM_LOCK_DURATION_SECONDS);
    }
    public EntitySynchronizer(int maximumLockDurationSeconds) {
      this.maximumLockDurationSeconds = maximumLockDurationSeconds;
    }
    /**
     * Initiate a lock for all threads with this key value
     * @param key the instance identifier for concurrency synchronization
     */
    public void lock(Object key) {
      if (key == null) {
        return;
      }
      /*
       * returns the existing lock for specified key, or null if there was no existing lock for the
       * key
       */
      ReentrantLock lock;
      synchronized (mutex) {
        lock = locks.putIfAbsent(key, new ReentrantLock(true));
        if (lock == null) {
          lock = locks.get(key);
        }
      }
      /*
       * Acquires the lock and returns immediately with the value true if it is not held by another
       * thread within the given waiting time and the current thread has not been interrupted. If this
       * lock has been set to use a fair ordering policy then an available lock will NOT be acquired
       * if any other threads are waiting for the lock. If the current thread already holds this lock
       * then the hold count is incremented by one and the method returns true. If the lock is held by
       * another thread then the current thread becomes disabled for thread scheduling purposes and
       * lies dormant until one of three things happens: - The lock is acquired by the current thread;
       * or - Some other thread interrupts the current thread; or - The specified waiting time elapses
       */
      try {
        /*
         * using tryLock(timeout) instead of lock() to prevent deadlock situation in case acquired
         * lock is not released normalRelease will be false if the lock was released because the
         * timeout expired
         */
        boolean normalRelease = lock.tryLock(maximumLockDurationSeconds, TimeUnit.SECONDS);
        /*
         * lock was release because timeout expired. We do not want to proceed, we should throw a
         * concurrency exception for waiting thread
         */
        if (!normalRelease) {
          throw new ConcurrentModificationException(
              "Entity synchronization concurrency lock timeout expired for item key: " + key);
        }
      } catch (InterruptedException e) {
        throw new IllegalStateException("Entity synchronization interrupted exception for item key: "
            + key);
      }
      keyThreadLocal.set(key);
    }
    /**
     * Unlock this thread's lock. This takes care of preserving the lock for any waiting threads with
     * the same entity key
     */
    public void unlock() {
      Object key = keyThreadLocal.get();
      keyThreadLocal.remove();
      if (key != null) {
        ReentrantLock lock = locks.get(key);
        if (lock != null) {
          try {
            synchronized (mutex) {
              if (!lock.hasQueuedThreads()) {
                locks.remove(key);
              }
            }
          } finally {
            lock.unlock();
          }
        } else {
          synchronized (mutex) {
            locks.remove(key);
          }
        }
      }
    }
  }
  </code></pre>
  
  <p>This class is used as follows:</p>
  
  <pre><code>private EntitySynchronizer entitySynchronizer = new EntitySynchronizer();
  entitySynchronizer.lock(userId);  // 'user' is the entity by which i want to differentiate my synchronization
  try {
    //execute my code here ...
  } finally {
    entitySynchronizer.unlock();
  }
  </code></pre>
  
  <p>The problem is that it doesn't work perfectly. At very high concurrency loads, there are still some cases wherein multiple threads with the same <em>key</em> are not being synchronized. I've been through and tested fairly thoroughly and cannot figure out why/where this can happen. </p>
  
  <p>Any concurrency experts out there?</p>