あなたの質問への答えはJLS #17.4.5にあります:
揮発性フィールド (§8.3.1.4) への書き込みは、そのフィールドの後続のすべての読み取りの前に発生します。
したがって、1つのスレッドにある場合
aNonVolatileVariable = 2 //w1
aVolatileVariable = 5 //w2
その後、別のスレッドで:
someVariable = aVolatileVariable //r1
anotherOne = aNonVolatileVariable //r2
anotherOne
その変数が揮発性でない場合でも、2 に等しいことが保証されます。そうです、volatile を使用すると、非 volatile 変数の使用にも副作用があります。
より詳細には、これは同じセクションで Java メモリ モデル (JMM) によって提供される他の 2 つの保証によるものです: スレッド内順序と推移性 ( hb(x,y)はx が y の前に発生することを意味します):
x と y が同じスレッドのアクションであり、プログラムの順序で x が y の前にある場合、hb(x, y) .
[...]
hb (x, y)とhb(y, z)の場合、hb(x, z) .
私の例では:
- hb(w1, w2)およびhb(r1, r2) (スレッド内セマンティクス)
- hb(w2, r1) volatile 保証のため
したがって、推移性によってhb(w1, r2)と結論付けることができます。
また、JMM は、プログラムが事前発生関係と正しく同期されている場合、プログラムのすべての実行が順次一貫している (つまり、何も並べ替えられていないように見える) ことを保証します。したがって、この特定のケースでは、不揮発性読み取りは、不揮発性書き込みの効果を見ることが保証されています。