4

次の Java コードを検討してください。

volatile boolean v1 = false;
volatile boolean v2 = false;

//Thread A
v1 = true;
if (v2)
    System.out.println("v2 was true");

//Thread B
v2 = true;
if (v1)
    System.out.println("v1 was true");

揮発性アクセスのグローバルに表示される合計注文があった場合、少なくとも 1 つの println に常に到達します。

それは実際にJava標準によって保証されていますか? または、このような実行は可能ですか:

A: v1 = true;
B: v2 = true;
A: read v2 = false;
B: read v1 = false;
A: v2 = true becomes visible (after the if)
B: v1 = true becomes visible (after the if)

標準で同じvolatile 変数へのアクセスに関するステートメントしか見つかりませんでした (ただし、何かが欠けている可能性があります)。

「揮発性変数への書き込み(§8.3.1.4)vは、任意のスレッドによるvの後続のすべての読み取りと同期します(後続は同期順序に従って定義されます)。」

http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.4.4

ありがとう!

4

6 に答える 6

2

v1/v2 の volatile read/write の 4 つのアクションは、すべて同期アクションです。実行には、全体の順序である同期順序があります。順序は、各スレッドのプログラム順序を維持する必要があります。

これにより、推論が非常に簡単になります。明らかに、少なくとも 2 つの変数のうちの 1 つについては、「同期順序」で、そこからの読み取りの前に、その変数への書き込みが順序付けられます。したがって、書き込みは読み取りと「同期」します。したがって、書き込みは読み取りの「前に発生」します。したがって、書き込みは読み取りに表示されます。

于 2010-03-31T22:54:16.973 に答える
1

引用はあなたが思っている以上にあなたの質問に答えると思います。

v22行目のスレッドによる書き込みは、変数を読み取ろうとしたときにBスレッドによって「認識」されます。A

引用の重要な部分を太字にしました。

「揮発性変数(§8.3.1.4)への書き込みvは、任意のスレッドによるvの後続のすべての読み取りと同期します...」

于 2010-03-31T18:35:07.207 に答える
0

という事実のため、実行の 3 行目は不可能v2ですvolatile

v2されていない場合volatile、スレッド A は、ローカルにキャッシュされv2たまだだったのコピーを見ることができますfalse

ただし、 は揮発性であるためv2、すべての読み取りは直接メイン メモリに送られるため、最後に書き込まれた値が表示されます。

とはいえ、異なるグローバル変数へのアクセス間に特定の順序保証があるとは思いませんが、それがあなたの例に違いをもたらすとは思いません。

于 2010-03-31T18:33:32.760 に答える
-1

ええと... volatile の定義により、v2 が B によって true に設定された場合、A はそれを false として読み取ることができません。

volatile は、単一の操作を実行するときにスレッド化するときに、データ型と参照が期待どおりに機能するようにします (したがって、++ と -- は機能しません!)

于 2010-03-31T18:33:40.357 に答える
-1

簡単に言うと、2 つの揮発性操作を並べ替えることができないため、少なくとも 1 回は出力されます。

仕様書のどこに書かれているのかわかりませんが、Doug Lea のサイトには、並べ替え可能な操作とそうでない操作の表があります。( http://gee.cs.oswego.edu/dl/jmm/cookbook.html )


スレッドの開始前に読み取りが初期化されるため、この状況はあり得ません。

違う!

A: v1 = true;
B: v2 = true; 
A: read v2 = false; // initialization happens before thread start
B: read v1 = false; // initialization happens before thread start

この状況でのみ可能です、v2 と v1 は揮発性であり、v1への書き込みは v2の読み取りの前に行う必要があり、v2 への書き込みは v1 の読み取りの前に行う必要があるため、これは不可能です。

違う!

volatile boolean v1 = false;
volatile boolean v2 = false;

//Thread A
if (v2)    //read v2
   System.out.println("v2 was true");
v1 = true; //write to v1

//Thread B
if (v1)    //read v1
    System.out.println("v1 was true");
v2 = true; //write v2
于 2011-07-23T11:04:24.127 に答える