Java:超类中的synchronized方法获取与子类中的同一个锁,对吧?

时间:2009-03-09 10:29:56

标签: java concurrency

class A {
    public synchronized void myOneMethod() {
        // ...
    }
}

class B extends A {
    public synchronized void myOtherMethod() {
        // ...
    }
}

// ...

B myObject;

// ...

myObject.myOneMethod(); // acquires lock
myObject.myOtherMethod(); // same lock?

我如何理解同步模型,我会说是的,确实如此,因为锁/监视器与实例myObject相关联,并且定义方法的位置无关紧要。但我是对的吗?如果没有,为什么?如果是的话,你为什么确定,我不是? : - )

7 个答案:

答案 0 :(得分:12)

是的,你是对的,你也得到了正确的解释。没什么可补充的。

请注意,如果方法是 static ,那么它们将在不同的对象上同步,即它们各自的类(A和B)。

编辑:为什么我确定?我不知道,你为什么不确定? ;-) myObject只是一个对象 - 来自A类的myObject属性与来自B类的属性之间没有任何区别。(从技术上讲,你可以使用反射来找出哪些是哪个,所以必须有一些的区别,但是暂时忘记反射。对于对象的常见操作没有区别。)

答案 1 :(得分:7)

是的,synchronized等同于synchronized(this)。

更多precise

  

对于类(静态)方法,使用与方法类的Class对象关联的锁。对于实例方法,使用与此关联的锁(调用该方法的对象)。

答案 2 :(得分:3)

如果您想更明确地了解锁定,可以执行以下操作:

class A {

    protected final Object  mutex = new Object();
    public void myOneMethod() {
        synchronized (mutex) {
            // ...
        }
    }
}

class B extends A {
    public  void myOtherMethod() {
        synchronized (mutex) {
            // ...
        }
    }
}

事实上,Brian Goetz在 Java Concurrency in Practice ,第4.2.1节“Java监视器模式”中推荐了这种模式。这样你就可以准确地知道显示器的来源。

答案 3 :(得分:1)

是。 Java使用“监视器”来实现同步,同步方法使用它们作为监视器调用的对象实例,在这种情况下显然是相同的。

请注意,静态方法不适用!在那里,使用了(我认为)声明类的类实例,它不会是同一个。

答案 4 :(得分:0)

是的,你是对的

当一个线程正在为对象执行同步方法时,所有其他线程都会调用同一对象的同步方法阻塞(暂停执行),直到第一个线程完成对象为止。在这种情况下,对象是B

答案 5 :(得分:0)

对于可能对未来感兴趣的人来说,这只是一小部分。

另外请记住,Java中的锁是可重入的。如果它们不是你的代码会导致死锁,因为你已经指出两个操作都需要相同的锁。

答案 6 :(得分:0)

从概念的角度来看,如果类synchonized的{​​{1}}方法只保护A的数据,那么某些继承方案的互斥完整性就会被破坏。子类A。毕竟,并非B的所有数据都必须为A

想象一下,您希望稍微扩展private的一种方法的功能,同时保留其余A的功能,包括互斥保护。如果A仅保护自己,则最终必须覆盖所有 A的{​​{1}}方法,以将原始同步机制解除新的子类。不是很有吸引力,也不是很有效率。