Search code examples
javamultithreadingconcurrencysynchronized

Could 2 threads execute the same synchronized instance method if the monitor object is different in Java?


I'm new to Java concurrency and I know that an instance method synchronized means that only one thread can execute that method at a time. But does this thing depends on the monitor object or not? Could 2 threads execute the same synchronized instance method in the same time if the monitor object is different?

Ex: This is an example but I'm not sure if it's a good one. I just want to know if it is possible to call a synchronized method or block by two or more threads simultaneously. Or always a synchronized method cannot be called by

public class SynchronizedExchanger {

    protected Object object = null;

    public synchronized void setObject(Object o) {
        System.out.println("Do something, o = " + o);
        this.object = o;
    }
}

public class SynchronizedExchangerMainDemo {
    public static void main(String[] args) {
        SynchronizedExchanger exchanger = new SynchronizedExchanger();
        SynchronizedExchanger exchanger1 = new SynchronizedExchanger();

        Thread thread1 = new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        for (int i = 0; i < 1000; i++) {
                            exchanger.setObject("" + i);
                        }
                    }
                }
        );

        Thread thread2 = new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        for (int i = 0; i < 1000; i++) {
                            exchanger1.setObject("" + i);
                        }
                    }
                }
        );

    }
}

Solution

  • In your example code, exchanger and exchanger1 refer to two distinct instances. The two threads absolutely can call setObject "at the same time," because setObject is synchronized on this, and this refers to the exchanger instance in one thread, but it refers to the exchanger1 instance in the other thread.

    synchronized(o) only prevents multiple threads from synchronizing on the same object o at the same time. And when you write:

    synchronized MyType mymethod(...) {
        doSomeStuff(...);
        return something;
    }
    

    That's just a shortcut for:

    MyType mymethod(...) {
        synchronized(this) {
            doSomeStuff(...);
            return something;
        }
    }
    

    It would be different if there was only one SynchronizedExchanger instance, and both threads were operating on it. In that case, this would refer to the same object in both threads, and the two threads would never both be allowed to be synchronized on it at any moment time.