Fundamentals 15 min read

Understanding Java synchronized and ReentrantLock: When Multiple Threads Can Access Synchronized Methods

This article examines how Java's synchronized keyword and ReentrantLock behave when multiple threads invoke two synchronized methods of the same class, exploring scenarios with the same instance, different instances, and Runnable run methods, and summarizing the resulting concurrency rules.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Understanding Java synchronized and ReentrantLock: When Multiple Threads Can Access Synchronized Methods

The article investigates whether multiple threads can simultaneously execute two synchronized methods within the same class, focusing on Java's synchronized keyword and ReentrantLock mechanism. It analyzes three situations for each locking technique: (1) threads accessing two synchronized methods on the same instance, (2) threads accessing the methods on different instances, and (3) threads invoking two Runnable run methods that contain synchronized blocks.

1. synchronized

Case 1: Multiple threads access two synchronized methods on the same instance.

package synchronizedTest;

public class Example1 {
    private int num = 0;
    public synchronized void method1() {
        System.out.println("同步方法1进入");
        for (int i = 0; i < 10; i++) {
            System.out.print("同步方法1:" + num + "--");
            num++;
        }
        System.out.println("同步方法1结束");
    }
    public synchronized void method2() {
        System.out.println("method2进入:");
        for (int i = 0; i < 10; i++) {
            System.out.print("method2:" + num + "--");
            num++;
        }
        System.out.println("method2结束");
    }
    public static void main(String[] args) {
        final Example1 example1 = new Example1();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() { example1.method1(); }
        });
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() { example1.method2(); }
        });
        try {
            thread2.join();
            thread1.join();
            thread1.start();
            thread2.start();
        } catch (InterruptedException e) { e.printStackTrace(); }
    }
}

Output shows that the two methods cannot run concurrently when they share the same object because synchronized locks the instance.

Case 2: Multiple threads access two synchronized methods on different instances.

final Example1 example2 = new Example1();
Thread thread2 = new Thread(new Runnable() {
    @Override
    public void run() { example2.method2(); }
});

The resulting output demonstrates that the methods can run concurrently when each thread works on a separate object.

Case 3: Multiple threads invoke two Runnable run methods that contain synchronized(this) blocks.

package synchronizedTest;

public class Example2 {
    private int num;
    public Runnable runnable1 = new Runnable() {
        @Override
        public void run() {
            synchronized (this) {
                System.out.println("线程1进入");
                for (int i = 0; i < 10; i++) {
                    System.out.print("线程1:" + num + "--");
                }
                System.out.println("线程1结束");
            }
        }
    };
    public Runnable runnable2 = new Runnable() {
        @Override
        public void run() {
            synchronized (this) {
                System.out.println("thread2进入");
                for (int i = 0; i < 10; i++) {
                    System.out.print("thread2:" + num + "--");
                }
                System.out.println("thread2结束");
            }
        }
    };
    public static void main(String[] args) {
        Example2 example = new Example2();
        new Thread(example.runnable1).start();
        new Thread(example.runnable2).start();
    }
}

Here the two threads can run concurrently because each synchronized(this) locks a different runnable instance.

2. ReentrantLock

Case 1: Same instance, two methods protected by the same ReentrantLock .

package ReentrantLockTest;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockExample {
    private int num;
    private Lock lock = new ReentrantLock();
    public void method1() {
        lock.lock();
        System.out.println("同步方法1进入");
        for (int i = 0; i < 10; i++) {
            System.out.print("同步方法1:" + num + "--");
            num++;
        }
        System.out.println("同步方法1结束");
        lock.unlock();
    }
    public void method2() {
        lock.lock();
        System.out.println("method2进入:");
        for (int i = 0; i < 10; i++) {
            System.out.print("method2:" + num + "--");
            num++;
        }
        System.out.println("method2结束");
        lock.unlock();
    }
    public static void main(String[] args) {
        final LockExample example = new LockExample();
        Thread thread1 = new Thread(() -> example.method1());
        Thread thread2 = new Thread(() -> example.method2());
        try {
            thread2.join();
            thread1.join();
            thread1.start();
            thread2.start();
        } catch (InterruptedException e) { e.printStackTrace(); }
    }
}

The output shows that the two methods cannot execute concurrently on the same object because they share the same ReentrantLock instance.

Case 2: Different instances, each with its own ReentrantLock .

final LockExample example1 = new LockExample();
final LockExample example2 = new LockExample();
Thread thread1 = new Thread(() -> example1.method1());
Thread thread2 = new Thread(() -> example2.method2());

In this scenario the methods run concurrently, confirming that distinct lock objects allow parallel execution.

Case 3: Two Runnable run methods using the same ReentrantLock inside a single instance.

package ReentrantLockTest;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Lockexample2 {
    private int num;
    private Lock lock = new ReentrantLock();
    public Runnable runnable1 = new Runnable() {
        @Override
        public void run() {
            lock.lock();
            System.out.println("线程1进入");
            for (int i = 0; i < 10; i++) {
                System.out.print("线程1:" + num + "--");
            }
            System.out.println("线程1结束");
            lock.unlock();
        }
    };
    public Runnable runnable2 = new Runnable() {
        @Override
        public void run() {
            lock.lock();
            System.out.println("thread2进入");
            for (int i = 0; i < 10; i++) {
                System.out.print("thread2:" + num + "--");
            }
            System.out.println("thread2结束");
            lock.unlock();
        }
    };
    public static void main(String[] args) {
        Lockexample2 example = new Lockexample2();
        new Thread(example.runnable1).start();
        new Thread(example.runnable2).start();
    }
}

Because both runnables share the same lock object, the second thread must wait, so the methods do not run concurrently.

3. Conclusion

For synchronized:

Two synchronized methods on the same instance cannot be executed concurrently.

Two synchronized methods on different instances can run concurrently.

When the synchronization is inside Runnable.run() with synchronized(this), each runnable has its own lock, allowing concurrent execution regardless of the instance.

For ReentrantLock:

Two methods protected by the same ReentrantLock on the same instance cannot run concurrently.

Methods on different instances (each with its own lock) can run concurrently.

The key takeaway is that both mechanisms lock on the object they are associated with; understanding which object is being locked determines whether threads can proceed in parallel.

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.

JavaconcurrencySynchronizationmultithreadingReentrantLocksynchronized
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

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.