当线程获取对象(例如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) {}
}
}
为什么与其他任何类相比,对象监视器锁在超类上的行为方式上固有的差异?
我对对象监视器锁的了解是否丢失了?
答案 0 :(得分:2)
我不确定您的问题是否有意义。没有所谓的“超类”实例,因为子类的实例与其超类的实例是一个相同的实例,否则,每次使用new
关键字时,您都将实例化多个对象。这也是为什么您无法执行以下操作的原因:
synchronized (super) {
}
最终,使用wait
和notify[All]
的能力属于Object
(因为它们是最终方法),它是每个类的超超类。您可以考虑在this
上进行同步就像在属于Object
的监视器上进行同步,因为内在锁与对象而不是类相关联(一个重要的区别是与{{1} }的对象)。
因此,由于Class
和A
都是B
的相同实例,因此在Object
中同步并调用{{1 }}来自B
,它们都指向同一个wait
。