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


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  

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

我应该使用 Lock 对象代替和/或不也使 method1(( 成为同步方法吗?

我想找到一种方法来防止method1((在调用syncdMethod1时运行

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

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

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

我应该改用 Lock 对象吗?

通常,使方法synchronized被认为不如使用private final锁定对象。 锁定对象只是允许您在锁中更细粒度。 例如,使用方法锁定,日志消息和其他不需要保护的语句也将synchronized。 但是,如果目标是锁定整个方法,则可以同步方法。

如果您希望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();
        }
    }
}

最新更新