我已经阅读了几个与此类似的问题,但没有一个答案提供了如何在保持锁完整性的同时清理内存的想法。我估计在给定时间键值对的数量是成千上万,但是在数据结构的整个生命周期中键值对的数量实际上是无限的(实际上它可能不会更多超过十亿,但我正在编码到最坏的情况)。锁定缓存键
我有一个接口:
public interface KeyLock<K extends Comparable<? super K>> {
public void lock(K key);
public void unock(K key);
}
有一个默认的实现:
public class DefaultKeyLock<K extends Comparable<? super K>> implements KeyLock<K> {
private final ConcurrentMap<K, Mutex> lockMap;
public DefaultKeyLock() {
lockMap = new ConcurrentSkipListMap<K, Mutex>();
}
@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();
}
}
这工作得很好,但地图上永远不会被清理。我至今一个干净的实现是:
public class CleanKeyLock<K extends Comparable<? super K>> implements KeyLock<K> {
private final ConcurrentMap<K, LockWrapper> lockMap;
public CleanKeyLock() {
lockMap = new ConcurrentSkipListMap<K, LockWrapper>();
}
@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();
}
}
}
这适用于两个线程访问单个按键锁定功能,但一旦第三线程引入了锁完整性不再保证。有任何想法吗?
忽略多余addReference()在锁定方法调用。我在尝试一些想法,并忘记在发布代码时将它们带出。 – user453385 2010-09-21 02:14:09