2017-06-04 7 views
0

私はJava環境(JDK 9-ea + 170を使用)で並べ替えの動作を調べようとしていますが、自分では説明できないものがあることが分かりました。ここでの例は次のとおり並べ替えが2つの揮発性変数で行われるのはなぜですか?

public class Client { 
    int x; 
    int y; 
    public void test() { 
     x++; 
     y++; 
    } 
    public static void main(String[] args) { 
     Client c = new Client(); 
     while(c.y <= c.x) new Thread(() -> c.test()).start(); 
     System.out.println(c.x + " " + c.y); 
    } 
} 

このプログラムは単にxとyの値をインクリメントtest()方法を有しています。いくつかの内部Java最適化が変更されない限り、新しいスレッドを作成してtest()と呼びます。x++; y++;命令の順序()。このようにして、並べ替えが実際に行われることが証明されます。プログラムはほとんどの場合終了します(これは予想されます)。 は、今私は、yにvolatile修飾子を追加しました:

public class Client { 
    int x; 
    volatile int y; 
    public void test() { 
     x++; 
     y++; 
    } 
    public static void main(String[] args) { 
     Client c = new Client(); 
     while(c.y <= c.x) new Thread(() -> c.test()).start(); 
     System.out.println(c.x + " " + c.y); 
    } 
} 

揮発する前にすべての命令がメモリにフラッシュされることを揮発性の保証はそうx++;は常にy++;前に実行し、それを持ってすることはできませんので、このプログラムが終了することはありませんy> xである。これは私の理解からも期待されます。プログラムは、ほとんどの時間を終了してしかし、私はあまりにも、今int x;に揮発追加したことの後に私は再びreorderingsを見ることができます:

public class Client { 
    volatile int x; 
    volatile int y; 
    public void test() { 
     x++; 
     y++; 
    } 
    public static void main(String[] args) { 
     Client c = new Client(); 
     while(c.y <= c.x) new Thread(() -> c.test()).start(); 
     System.out.println(c.x + " " + c.y); 
    } 
} 

並べ替えもここで行われるのはなぜ?

答えて

3

これは並べ替えの証拠ではありません。実際、何が起こっているのかは、volatile上の++がアトミックではないという結果です。

thread A: load x -> temp 
thread B: load x -> temp 
thread A: temp = temp + 1 
thread B: temp = temp + 1 
thread A: save temp -> x 
thread B: save temp -> x 

し、そのインターリーブとそれらの操作を通じて作業する場合、あなたはそれをあなたが表示されます。たとえば、変数(x)のいずれかを更新する際に、二つのスレッド(AB)による操作の次インターリーブを検討xでカウントを失った。 c.y <= c.xが時々失敗するのに十分です。

(「失われた回数」の行動も、この実験は唯一の時間の一部を失敗した理由を説明している... yで発生する可能性があります。)

+0

あなたはB> Aということが可能です方法の例を提供していただけますか? 上記で説明したフローでは、Aへの代入はBへの代入の前に行われます。 –

+0

1)変数は 'x'と' y'です。 「A」および「B」はスレッドを示す。 2)起こる必要があることは、あなたが 'y'で行うよりも' x'で多くのカウントを失うことです、そして 'y <= x'は' false'になります。 –

+0

ありがとうございました!今は私のために少し清潔です。スティーブン、今私は同じコードを実行しているが、test()上でsynchronizedキーワードを使用しています。それは、volatileがyまたはxとyにあるときにはうまくいくが、volatile(期待される)なしでは失敗し、xのみでvolatileで失敗する。それは正常な行動ですか?何が起こっているか知っているかどうかを説明してください。 –

関連する問題