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

时间:2011-10-05 06:52:54

标签: java jvm

我有以下课程:

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如何执行同步?

2 个答案:

答案 0 :(得分:6)

应用于方法的synchronized关键字只会在the JVM specification § 4.6 Methods中定义的方法定义上设置ACC_SYNCHRONIZED标记。它在方法的实际字节码中不可见。

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

volatile字段会产生类似的效果:它只是在字段JVM § 4.5 Fields)上设置ACC_VOLATILE标记。 访问字段的代码使用相同的字节码,但行为略有不同。

另请注意,此处仅使用 一个易失性字段非线程安全,因为易失性字段x++上的x不是原子的

答案 1 :(得分:4)

前两者的区别就在这里:

public int getNext();
   bytecodes follow...

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

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

int last;

volatile int lastVolatile;

如果/当字节码由JIT编译器编译成机器代码时,我确信最终方法的结果机器代码会有所不同。