2011-10-05 14 views
5

私は次のクラスを持っている:私は逆アセンブルコードを見てみると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が同期を実行する方法

答えて

6

​​キーワードは、the JVM specification § 4.6 Methodsで定義されているように、そのメソッド定義にACC_SYNCHRONIZEDフラグを設定するだけです。このメソッドの実際のバイトコードには表示されません。

JLS § 8.4.3.6 synchronized Methodsは​​メソッドを定義し、全体メソッド本体にまたがる​​ブロックを宣言(および上で同期させるために同じオブジェクトを使用して)の類似性を説明:効果はまったく同じであるが、それらは異なって表現されます.classファイルにあります。

同様の効果がvolatileフィールドで発生:これは単にフィールドJVM § 4.5 Fields)にACC_VOLATILEフラグを設定します。 がアクセスするコードフィールドは同じバイトコードを使用しますが、動作は少し異なります。

はまた、揮発性のフィールドxx++ないアトミックあるのでを使用してのみここで揮発性のフィールドは、ないスレッドセーフであることに注意してください!

4

最初の2つの違いは、右ここで:最後にとして

public int getNext(); 
    bytecodes follow... 

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

volatileは変数のではなく、方法又はその変数にアクセスJVMバイトコードのプロパティです。あなたがjavap出力の一番上を見れば、あなたは次のように表示されます:

int last; 

volatile int lastVolatile; 

バイトコードは、JITコンパイラによってマシンコードにコンパイルされたとき、私は結果のマシンコードがために異なります確信している/した場合最後の方法。