bouncingHippo
bouncingHippo

Reputation: 6040

Thread calling non-synchronized instance method when a synchronized method is called

public class Common {      
    public synchronized void synchronizedMethod1() {
        System.out.println("synchronizedMethod1 called");
        try {
            Thread.sleep(1000);
            } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("synchronizedMethod1 done");
    }
    public void method1() {
        System.out.println("Method 1 called");
        try {
            Thread.sleep(1000);
            } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Method 1 done");
    }
}



public class MyThread extends Thread {
    private int id = 0;
    private Common common;

    public MyThread(String name, int no, Common object) {
        super(name);
        common = object;
        id = no;
    }

    public void run() {
        System.out.println("Running Thread" + this.getName());
        try {
            if (id == 0) {
                common.synchronizedMethod1();
                } else {
                common.method1();
            }
            } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Common c = new Common();
        MyThread t1 = new MyThread("MyThread-1", 0, c);
        MyThread t2 = new MyThread("MyThread-2", 1, c);
        t1.start();
        t2.start();
    }
}

Output:

Running ThreadMyThread-1  
synchronizedMethod1 called  
Running ThreadMyThread-2  
Method 1 called  
synchronizedMethod1 done  
Method 1 done  

I would like to find a way to prevent method1() from running when i called synchronizedMethod1. Unless I'm mistaken all methods are called and Java compiles them during and before runtime regardless if it's synchronized or not.

Should i have used a Lock object instead and/or not also make method1() a synchronized method?

Upvotes: 0

Views: 1635

Answers (2)

Tim Bender
Tim Bender

Reputation: 20442

If you want method1 and synchronizedMethod1 to be mutually exclusive then you need to guard them with the same lock. Whether this is using a Lock or simply calling synchronize on the same Object instance, the outcome is roughly the same.

On the off chance you want multiple threads to be allowed to execute method1 but not when synchronizedMethod1 is being invoked, you need a ReadWriteLock to accomplish that.

public class Common {     
    ReadWriteLock rwLock = new ReentrantReadWriteLock();

    public void synchronizedMethod1() {
        rwLock.writeLock().lock();
        try {
            System.out.println("synchronizedMethod1 called");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("synchronizedMethod1 done");
        } finally {
            rwLock.writeLock().unlock();
        }
    }
    public void method1() {
        rwLock.readLock().lock();
        try {
            System.out.println("Method 1 called");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Method 1 done");
        } finally {
            rwLock.readLock().unlock();
        }
    }
}

Upvotes: 0

Gray
Gray

Reputation: 116858

I would like to find a way to prevent method1() from running when i called synchronizedMethod1

The easiest way to do this is to make method1() also be synchronized. This will mean that both methods will cause a lock on the instance of Common that they are calling. Only one thread will be able to either be calling synchronizedMethod1() or method1().

Unless I'm mistaken all methods are called and Java compiles them during and before runtime regardless if it's synchronized or not.

I don't understand this question. You really should not have to worry about the compilation or optimization phase of the JVM.

Should i have used a Lock object instead?

Usually making a method synchronized is considered not as good as using a private final lock object. Lock objects just allow you to be more fine grained in your locks. For example, with method locking, log messages and other statements that do not need protection will be synchronized as well. But if the goal is to lock the entire method then synchronizing the methods is fine.

Upvotes: 1

Related Questions