代码之家  ›  专栏  ›  技术社区  ›  somnathchakrabarti

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

  •  0
  • somnathchakrabarti  · 技术社区  · 6 年前

    当一个线程获得一个对象的监视锁(比如说类B)时,它是否获得了属于它的超类的对象的监视锁(比如类a,其中B扩展了a)?

    观察#1 -当一个线程(通过synchronized方法拥有派生对象B的监视锁)调用超类a中的wait()时,第二个线程获取对象B的监视锁并在a中等待。最后,两个线程同时退出B的对象监视器。

    我的理解是线程应该调用 wait()

    有关同步和;固有锁- 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 -当线程(通过synchronized方法拥有对象的monitor锁)在任意类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 回复  |  直到 6 年前
        1
  •  2
  •   user2982130 user2982130    6 年前

    我不确定你的问题是否有道理。不存在“超类”实例,因为子类的实例与其超类的实例是同一个实例,否则每次使用 new 关键字。这也是为什么你不能这样做的原因:

    synchronized (super) {
    }
    

    最终,使用 wait notify[All] 属于 Object (因为它们是final方法),这是每个类的超类。你可以考虑同步 this ,因为内在锁与对象而不是类相关联(一个重要的区别是内在锁与 Class 可以获取对象)。

    A B 对象 ,在中同步并不重要 打电话给我 A 对象