Fundamentals 25 min read

Comparison of synchronized and Lock in Java: Limitations, Advantages, and Usage

This article explains the limitations of Java's synchronized keyword, introduces the Lock framework from java.util.concurrent.locks, compares their features, and demonstrates practical usage through multiple code examples covering ReentrantLock, tryLock, lockInterruptibly, ReadWriteLock, and fairness concepts.

Java Captain
Java Captain
Java Captain
Comparison of synchronized and Lock in Java: Limitations, Advantages, and Usage

Abstract

We know that synchronized is a Java keyword implemented at the JVM level to provide mutual exclusion, but its granularity is coarse and it has limitations such as inability to respond to interruptions. The Lock interface offers more flexible locking operations and handles thread synchronization more elegantly. This article compares synchronized and Lock, introduces the core parts of Java's Lock framework, and presents related lock concepts.

1. Limitations of synchronized and Advantages of Lock

When a block is marked with synchronized, a thread that acquires the lock blocks all other threads until it releases the lock, which happens when the block finishes, an exception occurs, or the thread enters a waiting state (e.g., wait()).

Three scenarios illustrate why Lock is needed:

Case 1: A thread holding a lock may be blocked by I/O or sleep() , preventing other threads from proceeding. Lock can limit wait time ( tryLock(long, TimeUnit) ) or respond to interruptions ( lockInterruptibly() ).

Case 2: With multiple reader threads, synchronized forces exclusive access, while ReentrantReadWriteLock allows concurrent reads.

Case 3: Lock can report whether a lock was successfully acquired ( ReentrantLock ), which synchronized cannot.

Key differences:

synchronized is a JVM‑level keyword; Lock is a Java interface implemented at the JDK level.

synchronized releases the lock automatically; Lock requires explicit unlock() , otherwise deadlocks may occur.

2. Common Classes and Interfaces in java.util.concurrent.locks

The main hierarchy includes Lock, ReentrantLock, ReadWriteLock, ReentrantReadWriteLock, and related condition classes.

Lock hierarchy
Lock hierarchy

1. Lock Interface

The Lock interface defines the following methods:

public interface Lock {
    void lock();
    void lockInterruptibly() throws InterruptedException; // can respond to interruption
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // can respond to interruption
    void unlock();
    Condition newCondition();
}

Methods lock(), tryLock(), tryLock(long, TimeUnit), and lockInterruptibly() acquire the lock; unlock() releases it; newCondition() creates a Condition for thread coordination.

2. ReentrantLock

ReentrantLock

is the sole implementation of Lock and provides additional features. Example of correct usage:

public class Test {
    private ArrayList<Integer> arrayList = new ArrayList<>();
    private Lock lock = new ReentrantLock();
    public static void main(String[] args) {
        final Test test = new Test();
        new Thread("A") { public void run() { test.insert(Thread.currentThread()); } }.start();
        new Thread("B") { public void run() { test.insert(Thread.currentThread()); } }.start();
    }
    public void insert(Thread thread) {
        lock.lock();
        try {
            System.out.println("Thread " + thread.getName() + " got the lock...");
            for (int i = 0; i < 5; i++) {
                arrayList.add(i);
            }
        } finally {
            System.out.println("Thread " + thread.getName() + " releases the lock...");
            lock.unlock();
        }
    }
}

If the lock variable is declared locally, each thread gets a different lock, breaking mutual exclusion. Declaring it as a member variable fixes the issue.

3. tryLock() & tryLock(long, TimeUnit)

tryLock()

returns immediately with a boolean indicating success. The timed version waits up to the specified time and can be interrupted.

Lock lock = new ReentrantLock();
if (lock.tryLock()) {
    try { /* handle task */ } finally { lock.unlock(); }
} else {
    // do something else when lock not acquired
}

4. lockInterruptibly()

lockInterruptibly()

allows a waiting thread to be interrupted. Example:

public void method() throws InterruptedException {
    lock.lockInterruptibly();
    try {
        // ...
    } finally {
        lock.unlock();
    }
}

If a thread is interrupted while waiting, it throws InterruptedException. Unlike synchronized, which cannot be interrupted while waiting, Lock can.

5. ReadWriteLock

The ReadWriteLock interface defines two methods:

public interface ReadWriteLock {
    Lock readLock();
    Lock writeLock();
}

It separates read and write access, allowing multiple concurrent readers.

6. ReentrantReadWriteLock

Provides a concrete implementation of ReadWriteLock. Example showing concurrent reads:

public class Test {
    private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    public static void main(String[] args) {
        final Test test = new Test();
        new Thread("A") { public void run() { test.get(Thread.currentThread()); } }.start();
        new Thread("B") { public void run() { test.get(Thread.currentThread()); } }.start();
    }
    public void get(Thread thread) {
        rwl.readLock().lock();
        try {
            System.out.println("Thread " + thread.getName() + " starts read...");
            // simulate read work
            System.out.println("Thread " + thread.getName() + " read finished.");
        } finally {
            rwl.readLock().unlock();
        }
    }
}

7. Choosing between Lock and synchronized

(1) Lock is a JDK‑level interface; synchronized is a JVM‑level keyword.

(2) synchronized releases automatically on exception; Lock requires explicit unlock() in a finally block.

(3) Lock can respond to interruption; synchronized cannot.

(4) Lock can report acquisition success; synchronized cannot.

(5) Lock improves read‑heavy scenarios via read‑write locks.

When contention is low, performance is similar; under high contention, Lock generally outperforms synchronized.

3. Related Lock Concepts

1. Reentrant Lock

A lock is reentrant if the same thread can acquire it multiple times without deadlocking. Both synchronized and ReentrantLock are reentrant.

class MyClass {
    public synchronized void method1() { method2(); }
    public synchronized void method2() { }
}

2. Interruptible Lock

Locks that can be interrupted (e.g., Lock) allow a waiting thread to abandon the wait, unlike synchronized.

3. Fair Lock

A fair lock grants access in request order. ReentrantLock and ReentrantReadWriteLock are non‑fair by default but can be constructed as fair.

public class RunFair {
    public static void main(String[] args) throws InterruptedException {
        final Service service = new Service(true); // fair lock
        Runnable r = () -> {
            System.out.println("★Thread " + Thread.currentThread().getName() + " runs");
            service.serviceMethod();
        };
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) threads[i] = new Thread(r);
        for (Thread t : threads) t.start();
    }
}
class Service {
    private final ReentrantLock lock;
    public Service(boolean fair) { lock = new ReentrantLock(fair); }
    public void serviceMethod() {
        lock.lock();
        try { System.out.println("Thread " + Thread.currentThread().getName() + " got lock"); }
        finally { lock.unlock(); }
    }
}

Non‑fair lock example simply passes false to the constructor.

4. Lock Inspection Methods

isFair()

isLocked()

isHeldByCurrentThread()

hasQueuedThreads()

getHoldCount()

getQueueLength()

getWaitQueueLength(Condition)

These methods help monitor lock state and diagnose concurrency issues.

Scan the QR code below to follow the WeChat public account!

Daily Java tips shared!

QR Code
QR Code
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.

concurrencymultithreadingLocksynchronized
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

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.