Note that there are some explanatory texts on larger screens.

plurals
  1. POlocking on a cache key
    primarykey
    data
    text
    <p>I've read several questions similar to this, but none of the answers provide ideas of how to clean up memory while still maintaining lock integrity. I'm estimating the number of key-value pairs at a given time to be in the tens of thousands, but the number of key-value pairs over the lifespan of the data structure is virtually infinite (realistically it probably wouldn't be more than a billion, but I'm coding to the worst case).</p> <p>I have an interface:</p> <pre><code>public interface KeyLock&lt;K extends Comparable&lt;? super K&gt;&gt; { public void lock(K key); public void unock(K key); } </code></pre> <p>with a default implementation:</p> <pre><code>public class DefaultKeyLock&lt;K extends Comparable&lt;? super K&gt;&gt; implements KeyLock&lt;K&gt; { private final ConcurrentMap&lt;K, Mutex&gt; lockMap; public DefaultKeyLock() { lockMap = new ConcurrentSkipListMap&lt;K, Mutex&gt;(); } @Override public void lock(K key) { Mutex mutex = new Mutex(); Mutex existingMutex = lockMap.putIfAbsent(key, mutex); if (existingMutex != null) { mutex = existingMutex; } mutex.lock(); } @Override public void unock(K key) { Mutex mutex = lockMap.get(key); mutex.unlock(); } } </code></pre> <p>This works nicely, but the map never gets cleaned up. What I have so far for a clean implementation is:</p> <pre><code>public class CleanKeyLock&lt;K extends Comparable&lt;? super K&gt;&gt; implements KeyLock&lt;K&gt; { private final ConcurrentMap&lt;K, LockWrapper&gt; lockMap; public CleanKeyLock() { lockMap = new ConcurrentSkipListMap&lt;K, LockWrapper&gt;(); } @Override public void lock(K key) { LockWrapper wrapper = new LockWrapper(key); wrapper.addReference(); LockWrapper existingWrapper = lockMap.putIfAbsent(key, wrapper); if (existingWrapper != null) { wrapper = existingWrapper; wrapper.addReference(); } wrapper.addReference(); wrapper.lock(); } @Override public void unock(K key) { LockWrapper wrapper = lockMap.get(key); if (wrapper != null) { wrapper.unlock(); wrapper.removeReference(); } } private class LockWrapper { private final K key; private final ReentrantLock lock; private int referenceCount; public LockWrapper(K key) { this.key = key; lock = new ReentrantLock(); referenceCount = 0; } public synchronized void addReference() { lockMap.put(key, this); referenceCount++; } public synchronized void removeReference() { referenceCount--; if (referenceCount == 0) { lockMap.remove(key); } } public void lock() { lock.lock(); } public void unlock() { lock.unlock(); } } } </code></pre> <p>This works for two threads accessing a single key lock, but once a third thread is introduced the lock integrity is no longer guaranteed. Any ideas?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload