Sobes.tech
Middle

What are optimistic and pessimistic locking?

sobes.tech AI

Answer from AI

Optimistic and pessimistic locking are approaches to managing concurrent access to shared data in concurrent environments (multithreaded applications, databases).

Pessimistic Locking:

Assumes that conflicts when accessing data are likely. Before accessing a resource, a thread or transaction places a lock on it (exclusive or shared). Other threads attempting to access it will wait until the lock is released.

  • Pros: Ensures data integrity, simple to implement under low contention.
  • Cons: Can lead to stalls (deadlocks), reduced throughput under high contention.
  • Examples: synchronized keyword in Java, row or table locks in databases.
// Example of pessimistic locking in Java
public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++; // Lock on the object, only one thread can execute this method at a time
    }

    public synchronized int getCount() {
        return count;
    }
}

Optimistic Locking:

Assumes that conflicts when accessing data are unlikely. Data access occurs without locking. Before saving changes, it checks whether the data has been modified by another thread since it was read. If changes are detected, the operation is canceled and usually retried.

  • Pros: High throughput under low contention, no deadlock issues.
  • Cons: Conflicts may occur requiring retries, complicating logic. Not suitable for long-running operations or high conflict probability.
  • Examples: Compare-And-Swap (CAS) operations, version control in databases (e.g., using a version column or timestamp).
// Example of optimistic locking using CAS (java.util.concurrent.atomic)
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicCounter {
    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        // Attempt to atomically increase the value
        // If the value changes between read and update attempt, the operation retries
        count.incrementAndGet();
    }

    public int getCount() {
        return count.get();
    }
}

Comparison:

Characteristic Pessimistic Locking Optimistic Locking
Assumption Conflicts are likely Conflicts are unlikely
Approach Lock until access Access without lock, check at write
Under high conflict rate Can cause locks, reduce throughput Frequent retries, reduce performance
Under low conflict rate May create overhead High throughput
Deadlock issue Possible Impossible (from the perspective of resource contention)