In my code I'm using ReentrantReadWriteLock
to guard some paired read/write operations:
public class AgreementCache {
private final ConcurrentMap<String, Agreement> agreements = new ConcurrentHashMap<>();
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public Agreement putIntoCache(String key, Function<String, Agreement> valueSupplyingFunction) {
Lock lock = readWriteLock.writeLock();
try {
lock.lock();
return agreements.put(key, valueSupplyingFunction.apply(key));
} finally {
lock.unlock();
}
}
public void drainCache(Map<String, Agreement> destination) {
Lock lock = readWriteLock.readLock(); // <--- !!!
try {
lock.lock();
destination.putAll(agreements);
agreements.clear(); // <--- !!!
} finally {
lock.unlock();
}
}
public Agreement getFromCache(String key) {
Lock lock = readWriteLock.readLock();
try {
lock.lock();
return agreements.get(key);
} finally {
lock.unlock();
}
}
}
Here in put()
method I need to ensure that mapping function is executed atomically along with putting the computed value into the map. At the same time I need to enforce raceless drain()
operation, i.e. I need to make sure that no data will be put into the map while draining its contents. Currently I use writeLock
in put()
method and readLock()
in drain()
method, but I suspect this is wrong, because after map.putAll()
I clear the map which is a modifying operation.
So my question is whether I need to use writeLock
in drain()
method or I can still rely on readLock()
?