liveBook · Manning

Locking

As explained in Advanced Algorithms and Data Structures

A lock is a synchronization primitive that coordinates access to shared resources by allowing mutually exclusive ownership.

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

How Advanced Algorithms and Data Structures covers it

How deep it goes
Explains read/write compatibility, try-finally release, deadlock prevention, and latency trade-offs through cache implementations.
Examples
Uses Java LFU-cache get and set methods, lock-compatibility cases, and database cursor updates as concrete examples.
What it assumes
Assumes threads, shared resources, cache reads and writes, and basic data-structure operations.
What you can do after
Apply it via read and write locks with guaranteed release around shared cache operations.
How it connects
Connects locking with concurrency, deadlock, caches, databases, hash tables, and priority queues.

Also explained in

Compare how 18 books explain locking →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Advanced Algorithms and Data Structures. The section links point to the parts of the book it draws on.