簡體   English   中英

jvm同步和非同步方法之間的差異

[英]jvm differences between synchronized and non-synchronized methods

我有以下課程:

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

應用於方法的synchronized關鍵字僅在該方法定義上設置ACC_SYNCHRONIZED標志,如JVM規范 ACC_SYNCHRONIZED方法中所定義。 它在方法的實際字節碼中不可見。

JLS§8.4.3.6synchronized方法討論了定義synchronized方法和聲明跨越整個方法體的synchronized塊(並使用相同的對象進行同步)的相似性: 效果完全相同,但它們的表示方式不同在.class文件中。

volatile字段ACC_VOLATILE產生類似的效果:它只是在字段上設置ACC_VOLATILE標志( ACC_VOLATILE 字段 )。 訪問該字段的代碼使用相同的字節碼,但行為略有不同。

另請注意,此處使用volatile字段不是線程安全的 ,因為易失性字段x上的x++ 不是原子的

前兩個的區別就在這里:

public int getNext();
   bytecodes follow...

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

至於最后一個, volatile是變量的屬性,而不是方法或訪問該變量的JVM字節碼的屬性。 如果你查看javap輸出的頂部,你會看到以下內容:

int last;

volatile int lastVolatile;

如果/當字節碼由JIT編譯器編譯成機器代碼時,我確信最終方法的結果機器代碼會有所不同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM