同步方法和非同步方法之间的JVM差异

5

我有以下类:

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

JVM如何区分这些方法?

生成的代码与这些方法及其调用者相同。JVM如何执行同步操作?

2个回答

6
应用于方法的synchronized关键字仅在该方法定义中设置ACC_SYNCHRONIZED标志,如JVM规范第4.6节方法所定义。它在方法的实际字节码中不可见。 JLS § 8.4.3.6 synchronized Methods讨论了定义同步方法和声明跨越整个方法体的同步块(并使用相同的对象进行同步)之间的相似性:效果完全相同,但它们在.class文件中的表示方式不同。 volatile字段也会产生类似的影响:它只是在字段上设置ACC_VOLATILE标志(JVM § 4.5 Fields)。访问该字段的代码使用相同的字节码,但行为略有不同。
还请注意,在此仅使用volatile字段是不线程安全的,因为对于x上的x++操作不是原子的

4
第一和第二的区别就在这里:
public int getNext();
   bytecodes follow...

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

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

int last;

volatile int lastVolatile;

如果JIT编译器将字节码编译成机器码,我相信最后的方法生成的机器码会有所不同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接