[concurrency-interest] Named locks with String values

Dawid Kurzyniec dawidk at mathcs.emory.edu
Thu Nov 10 14:06:57 EST 2005


Gregg Wonderly wrote:

> Dawid Kurzyniec wrote:
>
>> Gregg Wonderly wrote:
>>
>>> I recently was working on some code where a method had to string 
>>> values comming into it, and these values indicate a SQL database 
>>> rowset that I want to lock access to.  I was trying to decide how I 
>>> wanted to the locking and then it dawned on me that I could do the 
>>> following.
>>>
>>>     public void getEntries( String use, String key, ... ) {
>>>         synchronized( (use+"/"+key).intern() ) {
>>>             ...
>>>         }
>>>     }
>>>
>> I was hoping that some EG member would comment, but in the absence of 
>> that:
>>
>> This looks reasonably legit to me, although feels a bit risky. One 
>> possible caveat is that it is "external" synchronization, and some 
>> other library used by your program might independently have the same 
>> idea. 
>
>
> What this is controlling is the synchronization of a set of property 
> values in a database.  There are multiple threads that are able to 
> delete all and insert all of the properties as they encounter 
> information during startup.  What happens is that one thread will 
> delete all the properties, and then another, will run a query and find 
> them all missing, and say ohh I need to update these.  Both threads 
> will then try the inserts, one or more of which will fail with a 
> duplicate key error.  This synchronization is only needed briefly, and 
> is, in fact isolated to just the threads running in this JVM.  All 
> other users of the data are read-only users.
>
> It does feel a bit risky, to me as well, but it was a quick way to see 
> that I had in fact found the location of conflicting access.  I can, 
> of course, create a real weakhashmap of locks, as I suggested in my 
> other followup.  And, I probably will.  But, I just found this to be 
> an interesting quick and easy way to create a named locking 
> mechanism.  It's not ultimate, nor, perhaps even realistic to use, but 
> just something that came to mind.

You're welcome to use:
http://dcl.mathcs.emory.edu/cgi-bin/viewcvs.cgi/software/util/src/edu/emory/mathcs/util/remote/locks/ReentrantDistributedLock.java?view=markup

To make this work in your scenario, you need either to modify the class 
a bit, or to write a dummy RemoteLock class, ensapsulating String 
instance, implementing equals and hashCode by delegating to that string, 
and otherwise having all operations no-op. Then, you can do:

Lock lock = new ReentrantDistributedLock(new DummyRemoteLock("foo"));
lock.lock();
try { ... } finally { lock.unlock(); }

Or even:

Lock lock = new ReentrantDistributedLock(new DummyRemoteLock("foo"));
lock.lock();
try { ... }
finally {
  lock = new ReentrantDistributedLock(new DummyRemoteLock("foo"));
  lock.unlock();
}

Of course you can write a factory method in DummyRemoteLock to simplify 
the invocation syntax, perhaps like this:

Lock lock = MyClass.lock("foo");
try { ... } finally { lock.unlock(); }

This class was designed for a bit more complex general case, where you 
need a distributed lock accessed by many JVMs and threads. Its purpose 
is to provide reentrancy and resolve local mutual exclusion within the 
JVM, so that threads within a single JVM do not contend on a remote 
lock, but only on the local lock, and so that a thread who obtained the 
lock does not make remote calls to re-enter the lock. We used it, with 
some other helper classes providing generic versions of CAS-based and 
Eisenberg-McGuire algorithms, to implement poor-man's distributed 
locking piggybacking on JNDI.

Regards,
Dawid



More information about the Concurrency-interest mailing list