[concurrency-interest] Problem with using an unbounded map of Mutex lock objects

Tim Peierls tim at peierls.net
Tue Jun 6 09:58:30 EDT 2006


On 6/6/06, Greg Luck <gluck at gregluck.com> wrote:
>
> One point to note. In Brian's implementation, getLockForKey(Serializable
> key) was synchronized. I think this is unncecessary and potentially harmful
> to scalability. Mine is not synchronized.
>

You need to make the locks field final for this to be safe. See, for
example, 16.3 of Java Concurrency in Practice .

You can remove the final keywords from the 2-arg constructor parameters.

One concern I have about the current API is that it doesn't observe the
rule/convention that blocking methods throw InterruptedException. This makes
it harder, for example, to write cancellable tasks for the Executor
framework if they call BlockingCache.get. Not a showstopper, but more work
for the user.

Another concern is that the public API requires client threads to follow
failed gets by puts to release the mutex. It's not flat-out wrong, but it
means observing a special protocol on the client side. Wouldn't it be safer
to have a get method that takes a value-producing object that can be used to
return a value for a key if the cache doesn't contain one? Then users can't
fail to observe the protocol.

Quick sketch:

interface Function<A, V> {
    V compute(A key);
}

// BlockingCache method
public V get(K key, Function<K, V> f) throws InterruptedException {...}

Function<BigInteger, BigInteger[]> factor = new Function<BigInteger,
BigInteger[]>() {
    public BigInteger[] call(BigInteger n) { return computeFactors(n); }
};

BlockingCache<BigInteger, BigInteger[]> cache = new
BlockingCache<BigInteger, BigInteger[]>();

BigInteger[] getFactors(BigInteger n) throws InterruptedException {
    return cache.get(n, factor);
}

--tim
-------------- next part --------------
An HTML attachment was scrubbed...
URL: /pipermail/attachments/20060606/46ad416b/attachment.html 


More information about the Concurrency-interest mailing list