jvm同步方法和非同步方法的区别

发布于 2024-12-08 09:31:07 字数 1610 浏览 0 评论 0原文

我有以下类:

public class SeqGenerator {

    int last = 0;
    volatile int lastVolatile = 0;

    public int getNext() {
        return last++;
    }

    public synchronized int getNextSync() {
        return last++;
    }

    public int getNextVolatile() {
        return lastVolatile++;
    }

    public void caller() {
        int i1 = getNext();
        int i2 = getNextSync();
        int i3 = getNextVolatile();
    }

}

当我查看反汇编代码时,我看不到三个方法 getNext()getNextSync()的表示之间的区别>getNextVolatile()

public int getNext();
  Code:
   0:   aload_0
   1:   dup
   2:   getfield    #2; //Field last:I
   5:   dup_x1
   6:   iconst_1
   7:   iadd
   8:   putfield    #2; //Field last:I
   11:  ireturn

public synchronized int getNextSync();
  Code:
   0:   aload_0
   1:   dup
   2:   getfield    #2; //Field last:I
   5:   dup_x1
   6:   iconst_1
   7:   iadd
   8:   putfield    #2; //Field last:I
   11:  ireturn

public int getNextVolatile();
  Code:
   0:   aload_0
   1:   dup
   2:   getfield    #3; //Field lastVolatile:I
   5:   dup_x1
   6:   iconst_1
   7:   iadd
   8:   putfield    #3; //Field lastVolatile:I
   11:  ireturn

public void caller();
  Code:
   0:   aload_0
   1:   invokevirtual   #4; //Method getNext:()I
   4:   istore_1
   5:   aload_0
   6:   invokevirtual   #5; //Method getNextSync:()I
   9:   istore_2
   10:  aload_0
   11:  invokevirtual   #6; //Method getNextVolatile:()I
   14:  istore_3
   15:  return

JMV 如何区分这些方法?

这些方法及其调用者生成的代码是相同的。 JVM如何进行同步?

I have the following class:

public class SeqGenerator {

    int last = 0;
    volatile int lastVolatile = 0;

    public int getNext() {
        return last++;
    }

    public synchronized int getNextSync() {
        return last++;
    }

    public int getNextVolatile() {
        return lastVolatile++;
    }

    public void caller() {
        int i1 = getNext();
        int i2 = getNextSync();
        int i3 = getNextVolatile();
    }

}

When I look at the disassembled code I don't see the difference between the representation of three methods getNext(), getNextSync() and getNextVolatile() .

public int getNext();
  Code:
   0:   aload_0
   1:   dup
   2:   getfield    #2; //Field last:I
   5:   dup_x1
   6:   iconst_1
   7:   iadd
   8:   putfield    #2; //Field last:I
   11:  ireturn

public synchronized int getNextSync();
  Code:
   0:   aload_0
   1:   dup
   2:   getfield    #2; //Field last:I
   5:   dup_x1
   6:   iconst_1
   7:   iadd
   8:   putfield    #2; //Field last:I
   11:  ireturn

public int getNextVolatile();
  Code:
   0:   aload_0
   1:   dup
   2:   getfield    #3; //Field lastVolatile:I
   5:   dup_x1
   6:   iconst_1
   7:   iadd
   8:   putfield    #3; //Field lastVolatile:I
   11:  ireturn

public void caller();
  Code:
   0:   aload_0
   1:   invokevirtual   #4; //Method getNext:()I
   4:   istore_1
   5:   aload_0
   6:   invokevirtual   #5; //Method getNextSync:()I
   9:   istore_2
   10:  aload_0
   11:  invokevirtual   #6; //Method getNextVolatile:()I
   14:  istore_3
   15:  return

How the JMV can distinguish between these methods?

The generated code is the same of these methods and also of their callers. How the JVM performs the synchronization?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

相思故 2024-12-15 09:31:07

应用于方法的 synchronized 关键字只是在该方法定义上设置 ACC_SYNCHRONIZED 标志,如 JVM 规范第 4.6 节方法。它在方法的实际字节码中不可见。

JLS § 8.4.3.6 同步方法 讨论定义 synchronized 方法和声明跨越整个方法体的 synchronized 块(并使用相同的对象来同步)的相似性on):效果完全相同,但它们在.class文件中的表示方式不同。

易失性字段也会发生类似的效果:它只是在字段上设置ACC_VOLATILE标志(JVM § 4.5 字段)。访问该字段的代码使用相同的字节码,但行为略有不同。

另请注意,这里使用易失性字段不是线程安全的,因为易失性字段x上的x++不是原子

The synchronized keyword applied to a method just sets the ACC_SYNCHRONIZED flag on that method definition, as defined in the JVM specification § 4.6 Methods. It won't be visible in the actual bytecode of the method.

The JLS § 8.4.3.6 synchronized Methods discusses the similarity of defining a synchronized method and declaring a synchronized block that spans the whole method body (and using the same object to synchronize on): the effect is exactly the same, but they are represented differently in the .class file.

A similar effect happens with volatile fields: It simply sets the ACC_VOLATILE flag on the field (JVM § 4.5 Fields). The code that accesses the field uses the same bytecode, but acts slightly different.

Also please note that using only a volatile field here is not threadsafe, because x++ on a volatile field x is not atomic!

以歌曲疗慰 2024-12-15 09:31:07

前两者之间的区别就在这里:

public int getNext();
   bytecodes follow...

public synchronized int getNextSync();
   bytecodes follow...

对于最后一个,volatile 是变量的属性,而不是访问该变量的方法或 JVM 字节码的属性。如果您查看 javap 输出的顶部,您将看到以下内容:

int last;

volatile int lastVolatile;

如果/当 JIT 编译器将字节码编译为机器代码时,我确信生成的机器代码将有所不同最后一个方法。

The difference between the first two is right here:

public int getNext();
   bytecodes follow...

public synchronized int getNextSync();
   bytecodes follow...

As to the last one, volatile is a property of the variable, not of the method or the JVM bytecodes that access that variable. If you look at the top of the javap output, you'll see the following:

int last;

volatile int lastVolatile;

If/when the bytecodes are compiled into machine code by the JIT compiler, I am sure the resulting machine code will differ for the last method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文