Locking coordinates concurrent access to shared resources by granting controlled ownership. A write lock gives its holder exclusive read and write access; other threads wait until release. section 7.7.3
A lock protects consistency while an operation changes shared state, but it can also create latency. Keep the protected region as small as correctness permits, and always release the lock even when an operation fails. section 7.7.3 section 7.1
Choose the lock according to the operation:
- Use a read lock for operations that do not modify the resource. Multiple threads may hold read locks concurrently when no write lock is held. section 7.7.5
- Use a write lock for mutations. A write lock excludes both readers and other writers, so all conflicting requests wait. section 7.7.5
- Acquire the lock before accessing shared cache fields, place the operation in a try block, and unlock in finally. section 7.7.3 section 7.7.5
Concurrent cache access
In an LFU cache, set acquires a write lock before updating or evicting entries, while get acquires a read lock before inspecting and updating the cached node. Reads can therefore proceed in parallel, whereas writes block conflicting access. section 7.7.3 section 7.7.5
Listing 7.10 Java concurrent LFU cache set
public boolean set(Key key, Value value) {
writeLock.lock(); #1
try { #2
if (this.hashTable.contains(key)) {
PriorityQueueNode node = this.hashTable.get(key);
node.setValue(value);
return node.updatePriority(node.getCounter());
} else if (this.getSize() >= this.maxSize) {
this.evictOneEntry(); #3
}
PriorityQueueNode newNode = this.elements.add(key, value, 1);
this.hashTable.put(key, newNode);
return true;
} finally { #4
writeLock.unlock(); #5
}
}
Inspect the Java cache mutation showing write-lock acquisition, try-finally protection, eviction, insertion, and guaranteed unlock. section 7.7.3

















