我已經閱讀了幾個與此類似的問題,但沒有一個答案提供瞭如何在保持鎖完整性的同時清理內存的想法。我估計在給定時間鍵值對的數量是成千上萬,但是在數據結構的整個生命週期中鍵值對的數量實際上是無限的(實際上它可能不會更多超過十億,但我正在編碼到最壞的情況)。鎖定緩存鍵
我有一個接口:
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