获取对象的监视器锁的线程是否也获取超类的对象锁?

时间:2018-09-29 19:58:27

标签: multithreading synchronization synchronized thread-synchronization

当线程获取对象(例如B类)的监视器锁时,是否获取了属于其超类(例如A类,B扩展了A的对象)的对象的监视器锁?

  

观察#1 -当线程(通过同步方法拥有派生对象B的监视器锁)调用超类A内的wait()时,第二个线程获取对象B的监视器锁并进入最后,两个线程同时退出B的对象监视器。

     

我的理解是,线程应在其拥有锁的对象上调用wait(),否则将导致IllegalMonitorStateException。在A的实例方法内部调用wait()时没有异常的原因,是否意味着拥有B对象锁的线程也拥有A对象的锁,它是超类?

有关同步和内部锁的已检查文章-What does intrinsic lock actually mean for a Java class? https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

public class Obs2 {
    public static void main(String[] args) {
        A a = new B();
        Thread t1 = new Thread(a);
        Thread t2 = new Thread(a);
        t1.start(); t2.start();
    }
}

class A implements Runnable {
    public void run() {
        try {
            wait(2000); // OK; No IllegalMonitorStateException
        } catch (InterruptedException e) {}
    }
}
class B extends A {
    @Override
    public synchronized void run() {
        super.run();
    }
}
  

观察#2 -当线程(通过同步方法拥有对象A的监视器锁)在任意任意类C内调用wait()时,它将引发IllegalMonitorStateException。

     

这表明线程在C的对象上调用wait(),而它拥有对象A的锁,而锁不同。因此是例外。

public class Obs2 {
    public static void main(String[] args) {
        A a = new A();
        Thread t1 = new Thread(a);
        Thread t2 = new Thread(a);
        t1.start(); t2.start();
    }

}

class A implements Runnable {
    public synchronized void run() {
        (new C()).display(this);
    }

}

class C {
    public void display() {
        try {
            wait(2000); //--> will lead to IllegalMonitorStateException
        } catch (InterruptedException e) {}
    }
}

为什么与其他任何类相比,对象监视器锁在超类上的行为方式上固有的差异?

我对对象监视器锁的了解是否丢失了?

1 个答案:

答案 0 :(得分:2)

我不确定您的问题是否有意义。没有所谓的“超类”实例,因为子类的实例与其超类的实例是一个相同的实例,否则,每次使用new关键字时,您都将实例化多个对象。这也是为什么您无法执行以下操作的原因:

synchronized (super) {
}

最终,使用waitnotify[All]的能力属于Object(因为它们是最终方法),它是每个类的超超类。您可以考虑在this上进行同步就像在属于Object的监视器上进行同步,因为内在锁与对象而不是类相关联(一个重要的区别是与{{1} }的对象)。

因此,由于ClassA都是B的相同实例,因此在Object中同步并调用{{1 }}来自B,它们都指向同一个wait