调用synchronized方法时,线程调用非同步实例方法

时间:2012-07-18 20:05:44

标签: java multithreading synchronization thread-safety

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();
    }
}

输出:

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

我想找到一种方法来防止当我调用synchronizedMethod1时method1()运行。除非我弄错了所有方法都被调用,并且Java在运行时期间和之前编译它们,无论它是否同步。

我是否应该使用Lock对象和/或不使method1()成为同步方法?

2 个答案:

答案 0 :(得分:1)

  

我想在我调用synchronizedMethod1

时找到一种方法来防止method1()运行

最简单的方法是让method1()也成为synchronized。这意味着两种方法都会导致他们正在调用的Common实例上的锁定。只有一个线程可以调用synchronizedMethod1()method1()

  

除非我弄错了所有方法都被调用,并且Java在运行期间和之前编译它们,无论它是否已同步。

我不明白这个问题。您真的不必担心JVM的编译或优化阶段。

  

我应该使用Lock对象吗?

通常认为方法synchronized不如使用private final锁定对象。锁定对象只允许您在锁中更精细。例如,通过方法锁定,日志消息和其他不需要保护的语句也将是synchronized。但如果目标是锁定整个方法,那么同步方法就没问题了。

答案 1 :(得分:0)

如果您希望method1synchronizedMethod1互斥,那么您需要使用相同的锁来保护它们。无论是使用Lock还是仅在同一个Object实例上调用synchronize,结果大致相同。

如果您希望允许多个线程执行method1,而不是在调用synchronizedMethod1时,则需要ReadWriteLock来完成此操作。

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();
        }
    }
}