Mastering Locks: Optimistic, Pessimistic, and Distributed Strategies for High-Concurrency Systems

This article explains the different lock types—pessimistic, optimistic, and distributed—covers their use cases, compares their advantages and drawbacks, and provides concrete code examples and four practical solutions for handling high‑concurrency deduction scenarios such as inventory or balance reduction.

Programmer DD
Programmer DD
Programmer DD
Mastering Locks: Optimistic, Pessimistic, and Distributed Strategies for High-Concurrency Systems
How can we ensure that a method or a piece of code is executed by only one thread at a time under high concurrency? In monolithic applications we can use concurrency APIs, but after moving to a distributed micro‑service architecture, cross‑process locking is no longer possible. This article discusses lock types, why we use them, and typical lock scenarios.

Lock Types

Pessimistic Lock (synchronize)

Heavyweight lock in Java: synchronize Database row lock

Optimistic Lock

Lightweight lock in Java: volatile and CAS

Database version number

Distributed Lock (Redis lock)

Optimistic Lock

Think of an optimistic person who always assumes the best case. When you read shared data you assume nobody will modify it, so you don’t lock; when you update you first check whether someone else has changed the data.

Optimistic lock follows a "check‑first, act‑later" pattern. Example pseudocode:

reduce(){
    select total_amount from table_1
    if (total_amount < amount) {
        return failed;
    }
    // other business logic
    update total_amount = total_amount - amount where total_amount > amount;
}

Database version numbers are a form of optimistic lock.

CAS‑based implementations in Java are also optimistic locks.

Pessimistic Lock

Pessimistic lock assumes the worst case: every time you read data it might be modified by others, so you lock it before use and release the lock after you finish.

Pessimistic lock follows a "lock‑first, use‑later" pattern. Example pseudocode:

reduce(){
    // other business logic
    int num = update total_amount = total_amount - amount where total_amount > amount;
    if(num == 1){
        // business logic
    }
}

Java synchronize is a heavyweight pessimistic lock.

Database row lock is also a pessimistic lock.

Deduction Operation Example

A common high‑concurrency scenario is balance or inventory deduction. Without proper locking, overselling can occur, i.e., the quantity becomes negative.

Example: inventory is 100. Two concurrent requests each try to sell 100, resulting in a negative stock.

Solution 1: Synchronous Exclusive Lock

The simplest approach is a synchronized exclusive lock ( synchronize), but it has obvious drawbacks:

Thread serialization leads to performance degradation.

It cannot solve cross‑process locking in distributed deployments.

Solution 2: Database Row Lock

Locking the specific row in the database solves the cross‑process issue, yet it still suffers from:

Performance impact because the transaction blocks until commit.

Need to set the transaction isolation level to READ COMMITTED to avoid oversell.

Potential to exhaust database connections if the transaction involves long‑running external calls.

Risk of deadlocks when multiple business processes lock different rows.

Solution 3: Redis Distributed Lock

Redis (or Zookeeper) can act as a distributed lock service, offloading lock management from the application code.

Advantages:

Avoids heavy use of database exclusive locks, improving response time.

Disadvantages:

Ensuring atomicity of lock acquisition and expiration.

Handling cases where expiration is not set.

Dealing with service crashes or thread timeouts.

Choosing a reasonable lock timeout.

Redis SETNX plus EXPIRE were not atomic before version 2.6.12, which could cause deadlocks. Newer versions allow setting expiration atomically.

Even with atomic commands, long‑running business logic can cause the lock to expire while the thread is still processing, leading to accidental unlocks. A “renewal lock” (watchdog thread) can periodically extend the expiration, but it adds complexity.

Solution 4: Database Optimistic Lock

Optimistic locking reduces the lock scope. Example pseudocode:

reduce(){
    select total_amount from table_1
    if (total_amount < amount) {
        return failed;
    }
    // other business logic
    update total_amount = total_amount - amount where total_amount > amount;
}

If the UPDATE returns 0 rows, another thread has already performed the deduction, preventing negative values.

Two implementation ideas:

Use a transaction: throw an exception when the update affects 0 rows, causing a rollback of preceding operations.

reduce(){
    select total_amount from table_1
    if (total_amount < amount) {
        return failed;
    }
    // other business logic
    int num = update total_amount = total_amount - amount where total_amount > amount;
    if(num == 0) throw Exception;
}

Separate the update from other logic and handle the 0‑row case explicitly.

reduce(){
    // other business logic
    int num = update total_amount = total_amount - amount where total_amount > amount;
    if(num == 1){
        // business logic
    } else {
        throw Exception;
    }
}

This approach works well for high‑concurrency deductions, though extreme cases like OOM or service crashes still require manual intervention.

Summary

If you are proficient, you’ll first consider database version numbers or a distributed lock solution. Beginners often start with Java synchronized locks or database row locks. The goal is to understand the trade‑offs of each lock type and apply the most suitable one to high‑concurrency shared‑resource scenarios.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javadistributed-lockoptimistic lockpessimistic-lock
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.