当前位置:  开发笔记 > 编程语言 > 正文

用于Java中的实例方法同步的等效代码

如何解决《用于Java中的实例方法同步的等效代码》经验,为你挑选了2个好方法。

在讨论Java同步问题时,有人评论说下面的代码片段不相同(并且可能编译为不同的字节码):

public synchronized void someMethod() {
  //stuff
}

public void someMethod() {
  synchronized (this) {
    //stuff
  }
}

它们是等价的吗?



1> Dave L...:

虽然我测试的编译器(Java 1.6.0_07和Eclipse 3.4)生成不同的字节码,但它们在功能上是等价的.第一个产生:

// access flags 33
public synchronized someMethod()V
  RETURN

第二个产生:

// access flags 1
public someMethod()V
  ALOAD 0
  DUP
  MONITORENTER
  MONITOREXIT
  RETURN

(感谢ASM进行字节码打印).

因此它们之间的区别仍然存在于字节码级别,并且由JVM决定它们的行为是否相同.但是,它们确实具有相同的功能效果 - 请参阅Java语言规范中的示例.

应该注意的是,如果在子类中重写该方法,则它不一定是同步的 - 因此在这方面也没有区别.

我还运行了一个测试来阻止一个线程试图在每种情况下访问监视器,以比较它们的堆栈跟踪在线程转储中的样子,并且它们都包含有问题的方法,因此也没有区别.



2> Yuval Adam..:

我做了原始评论,声明是相同的.

在这两种情况下,首先发生的事情是调用线程将尝试获取当前对象(意思是this')监视器.

我不知道不同的字节码,我会很高兴听到差异.但在实践中,它们是完全相同的.

编辑:我将澄清这一点,因为有些人在这里弄错了.考虑:

public class A {
    public synchronized void doStuff()
    {
        // do stuff
    }
}

public class B extends A {
    public void doStuff()
    {
        // do stuff
        // THIS IS OVERRIDE!
    }
}

在这种情况下doStuff(),doStuff()即使不同步,B类仍会覆盖A类.

同步关键字永远不是合同的一部分!不适用于子类,不适用于接口,不适用于抽象类.

推荐阅读
女女的家_747
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有