Mastering Java Locks: When to Use synchronized vs ReentrantLock

This article explains how Java locks solve concurrent access problems, compares the built‑in synchronized lock with ReentrantLock, describes their upgrade mechanisms, usage patterns, and scenarios, and offers guidance on choosing the appropriate lock for different environments.

Ops Development Stories
Ops Development Stories
Ops Development Stories
Mastering Java Locks: When to Use synchronized vs ReentrantLock

Preface: When I first saw the title I felt it was both familiar and unfamiliar, because locks are an effective way to guarantee atomic operations on critical resources in concurrent situations. Below we discuss the locks we commonly use as developers.

What problems can locks solve?

Locks address scenarios where multiple threads need sequential access or modification of shared data, such as parallel deductions or transfers on the same account. We will discuss synchronized, ReentrantLock, and their usage.

synchronized

synchronized is a built‑in lock provided by the JDK, implemented by the JVM based on the monitor mechanism. After JDK 1.6 it was optimized and includes a lock‑upgrade process that stores lock state in the object header.

The upgrade process starts with no lock, then checks for contention. If there is none, a biased lock is used, which records the owning thread ID in the object header. It then upgrades to a lightweight lock, implemented via CAS modifying the MarkWord. Finally it may upgrade to a heavyweight lock, which relies on the operating system's mutex.

Four usage ways

Use on static methods

Use on ordinary methods

Lock the this object

Lock a static class

Lock state record location

When an object is locked, the lock information is recorded in the object header, as shown in the diagram below.

During runtime, the data stored in the MarkWord changes as the lock flag changes. The MarkWord can store four different kinds of data, illustrated in the next diagram.

Lock inflation and upgrade

The inflation and upgrade of a lock are irreversible.

Usage scenarios

In the JDK concurrency package, synchronized is used in places such as:

ConcurrentHashMap (JDK 1.8)

Hashtable

ReentrantLock

ReentrantLock

was added to the JDK starting from version 1.5, authored by Doug Lea. It implements locking via the AQS framework, using CAS operations provided by the Unsafe package to compete for the lock state, and employs LockSupport.park to block threads until they are awakened. ReentrantLock comes in fair and non‑fair variants; the default is non‑fair because fair locks enforce acquisition order at the cost of performance.

The AQS queue structure is a FIFO thread‑safe synchronization queue, as shown below.

The lock and unlock process of ReentrantLock is illustrated in the following diagram.

Usage method

Using ReentrantLock involves three steps: create, lock, and unlock.

class X {
    private final ReentrantLock lock = new ReentrantLock();
    // ...
    public void m() {
        lock.lock(); // block until condition holds
        try {
            // ... method body
        } finally {
            lock.unlock();
        }
    }
}

Usage scenarios

ReentrantLock is used in many JDK concurrency utilities, including:

CyclicBarrier

DelayQueue

LinkedBlockingDeque

ThreadPoolExecutor

ReentrantReadWriteLock

StampedLock

ReentrantLock is a fundamental class in the concurrency package and serves as a basis for learning concurrent programming.

How to choose a lock?

In a single‑machine environment, use synchronized (built‑in lock) or ReentrantLock for concurrency control.

For atomic counters, use atomic classes provided by Unsafe, such as AtomicInteger and AtomicLong.

For database operations like deducting user balances, use optimistic locking with SQL like:

update table_name set amount = 100, version = version + 1 where id = 1 and version = 1;

In distributed scenarios, ensure consistency with distributed locks implemented via Redis or ZooKeeper.

Reference information

"深入理解 Java 虚拟机" by 周志明

https://blog.csdn.net/wangbo199308/article/details/108688109

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.

JavaconcurrencymultithreadingLocksReentrantLocksynchronized
Ops Development Stories
Written by

Ops Development Stories

Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.

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.