Search code examples
javaalgorithmsynchronizationlocking

How to acquire a lock by a key


What is the best way to prevent concurrent update of one record in a key-value set without locking the entire set? Semantically, I'm looking for some kind of locking by a key (ideally, Java implementation, but not necessarily):

interface LockByKey {
   void lock(String key); // acquire an exclusive lock for a key   
   void unlock(String key); // release lock for a key
}

This lock is intended to synchronize an access to a remote store, so some synchronized Java collection is not an option.


Solution

  • Guava has something like this being released in 13.0; you can get it out of HEAD if you like.

    Striped<Lock> more or less allocates a specific number of locks, and then assigns strings to locks based on their hash code. The API looks more or less like

    Striped<Lock> locks = Striped.lock(stripes);
    Lock l = locks.get(string);
    l.lock();
    try {
      // do stuff 
    } finally {
      l.unlock();
    }
    

    More or less, the controllable number of stripes lets you trade concurrency against memory usage, because allocating a full lock for each string key can get expensive; essentially, you only get lock contention when you get hash collisions, which are (predictably) rare.

    (Disclosure: I contribute to Guava.)