class Cache<K.V> {
final Map<K, V> m = new HashMap<>();
final ReadWriteLock rwl = new ReentrantReadWriteLock();
/ / read lock
final Lock r = rwl.readLock();
/ / write locks
final Lock w = rwl.writeLock();
/ / read the cache
V get(K key) {
r.lock();
try {
return m.get(key);
} finally{ r.unlock(); }}/ / write cache
V put(K key, V value) {
w.lock();
try {
return m.put(key, value);
} finally{ w.unlock(); }}Copy the code
On-demand cache
// Cache on demand
V getIfNeed(K key) {
V v = null;
/ / read the cache
r.lock();
try {
v = m.get(key);
} finally {
r.unlock();
}
// It exists in the cache
if(v ! =null) {
return v;
}
// Do not exist in cache, query database
w.lock();
try {
// Verify again
// Other threads may have queried the database
v = m.get(key);
if (v == null) {
// Query the databasev = getFromSQL(); m.put(key, v); }}finally {
w.unlock();
}
return v;
}
Copy the code
Lock escalation
// Lock upgrade status
private void lockUpgrade(K key, V v) {
/ / read the cache
r.lock();
try {
v = m.get(key);
if (v == null) {
// At this point, the read lock is not released, and the write lock is blocked, that is, the lock is not allowed to upgrade
w.lock();
try {
// Validate again and update the cache
// omit detailed code
} finally{ w.unlock(); }}}finally{ r.unlock(); }}// The lock is degraded
private void lockDegrade(K key) {
w.lock();
try {
// Check the status again
if(! cacheValid()) { V data = getFromSQL(); m.put(key, data); }// Downgrade to read lock before releasing write lock
// Downgrade is ok
r.lock();
} finally {
// Release the write lock
w.unlock();
}
try {
// The read lock is still held here
m.get(key);
} finally{ r.unlock(); }}private boolean cacheValid(a) {
return false;
}
private V getFromSQL(a) {
return null; }}Copy the code