I implemented a cache with using WeakHashMap and ReentrantReadWriteLock, my code is like that:
class Demo<T, K> {
private final ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock();
private final Map<T, K> CACHE = new WeakHashMap<>();
public K get(T t) {
ReentrantReadWriteLock.ReadLock readLock = LOCK.readLock();
ReentrantReadWriteLock.WriteLock writeLock = LOCK.writeLock();
readLock.lock();
if(CACHE.containsKey(t)){
//-- question point --
K result = CACHE.get(t);
readLock.unlock();
return result;
}
readLock.unlock();
K result = // find from db;
writeLock.lock();
CACHE.put(t,result);
writeLock.unlock();
return result;
}
}
My question is that whill it happen that gc is excuted after if(CACHE.containsKey(t)) but before K result = CACHE.get(t); with read lock and lead to that if(CACHE.containsKey(t)) is true but K result = CACHE.get(t); get null.
Your
ReentrantReadWriteLockhas no control over the behavior of theWeakHashMapwith regards to the garbage collector.The class javadoc for
WeakHashMapstatesIn other words, yes, it's possible for your
containsKeycall to returntrueand thegetthat follows to returnfalse, if the garbage collector acts in between the two calls (and you have no other strong references to the corresponding key).You can verify this behavior with a small program like
which prints