Java中实例方法同步的等价代码

2022-01-22 00:00:00 synchronization java

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

While discussing a Java synchronization question, someone made a comment that the following snippets are not equivalent (and may compile to different bytecodes):

public synchronized void someMethod() {
  //stuff
}

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

它们是等价的吗?

推荐答案

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

They are equivalent in function, though the compilers I tested (Java 1.6.0_07 and Eclipse 3.4) generate different bytecode. The first generates:

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

第二个生成:

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

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

(Thanks to ASM for the bytecode printing).

因此它们之间的差异持续到字节码级别,并且由 JVM 来使它们的行为相同.但是,它们确实具有相同的功能效果 - 请参阅 example 在 Java 语言规范中.

So the difference between them persists to the bytecode level, and it's up to the JVM to make their behavior the same. However, they do have the same functional effect - see the example in the Java Language Specification.

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

It should be noted, that if the method is overridden in a subclass, that it is not necessarily synchronized - so there is no difference in that respect either.

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

I also ran a test to block a thread trying access the monitor in each case to compare what their stack traces would look like in a thread dump, and they both contained the method in question, so there is no difference there either.

相关文章