【问题标题】:Java: A synchronized method in the superclass acquires the same lock as one in the subclass, right?Java:超类中的同步方法获得与子类中相同的锁,对吗?
【发布时间】:2009-03-09 10:29:56
【问题描述】:
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 相关联,并且在哪里定义方法并不重要。但我说得对吗?如果不是,为什么?如果是,为什么你确定,而我不是? :-)

【问题讨论】:

    标签: java concurrency


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

      要多precise

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

      【讨论】:

        【解决方案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 并发实践第 4.2.1 节“Java 监视器模式”中推荐了这种模式。这样您就可以准确地知道显示器的来源。

        【讨论】:

        • 是的。此外,这就是 Jon Skeet 所做的:stackoverflow.com/questions/609963/… ;) 我将使用该模式,除了那些实际上最有意义锁定“this”的方法。
        • 感谢您提及这种方法。尽管如此,原始的 Q 可能指的是来自库的 A 类。至少,这就是我搜索该主题的原因。在这种情况下,似乎需要考虑其他因素。
        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

          是的,你是对的

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

          【讨论】:

            【解决方案6】:

            对于可能对未来感兴趣的人来说,只是一个小小的补充..

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

            【讨论】:

              【解决方案7】:

              从概念的角度来看,如果类Asynchonized 方法仅在子类B 的上下文中保护A 的数据,则某些继承方案的互斥完整性将被破坏。毕竟不是A的所有数据都必须是private

              假设您想稍微扩展A 的一种方法的功能,同时保留A 的其余功能,包括互斥保护。如果A 只是保护自己,您最终将不得不重写所有 Asynchronized 方法以将原始同步机制提升到新的子类。不是很有吸引力,也不是很有效。

              【讨论】:

                猜你喜欢
                • 2017-10-08
                • 1970-01-01
                • 2014-03-29
                • 1970-01-01
                • 2014-10-04
                • 2010-10-01
                • 2014-08-29
                • 1970-01-01
                相关资源
                最近更新 更多