2012-02-08 4 views
10

私の知る限り、揮発性変数はスレッドをメインCPU(各スレッドのキャッシュではない)に直接読み書きさせるので、他のスレッドにその変更を可視化します。揮発性:なぜコンパイラのリオーダコードを防止するのですか

私が知らないことは:だから、なぜこの作業(揮発性の)がコードのコンパイラ/ CPU並べ替えのステートメントを防ぐことができますか。

感謝:)

+0

揮発づくりについては、この事はキャッシュを避ける読み込むことに注意してくださいは、純粋に理論的な構造であると、本当に 'volatile'は、実際に本物のハードウェア上で何を行うにはすべてのことはあまりありません。我々は、実装が行うことができるすべての種類のものがあり、最適化が特定の場合には禁止する必要がある特定の動作を生成しないことを「揮発性」が保証していると考えています。 –

答えて

16

は、並べ替えの禁止は、(hereから取られた)に対処することを目的としている問題を説明するための非常に良い例です。この例では

class VolatileExample { 
    int x = 0; 
    volatile boolean v = false; 
    public void writer() { 
     x = 42; 
     v = true; 
    } 
    public void reader() { 
     if (v == true) { 
      //uses x - guaranteed to see 42. 
     } 
    } 
} 

vは揮発性であるが、xではありません。ライターとリーダーが同時に実行され、リーダーががtrueに設定されていると見ると、x42であることが保証されます。 Java-5以前は、コンパイラはxvに書き直しを自由にしていたので、の後にxが表示され、の後にtrueに設定されています。これは混乱し、微妙なエラーにつながりました。 Java-5メモリモデルは、同期とほぼ同等の揮発性書き込みを行うことで、この問題に対処しました。

+1

x = 42がv = trueになる前に起こる可能性がありますが、reader()はキャッシュされた値が0であることを確認できますか? – Shawn

+1

@Shawn Java-5が正しければ、Java-5メモリーモデルはすべての書き込みが揮発性書き込みの前に完了するようにします。詳細はリンクを参照してください。 – dasblinkenlight

+0

おかげで、知っておいてよかった! – Shawn

5

言語が定義されているだけの方法です。非形式的には、変数volatileをJavaでマークすると、コンパイラは、別のスレッドでその値が同時に変更される可能性があるため、その前後のステートメントを並べ替えたり、その値を最適化したりするべきではないことをコンパイラーに通知します。この場合、JVMの特定の実装は、このvolatile修飾子を尊重し、プログラムを誤って最適化しないように適切な予防策を講じる責任があります。

volatileが正しく機能することを保証する言語レベルの保証について詳しくは、the Java Language Specification's description of the Java memory modelを参照してください。これはスレッドの動作を規定する抽象的なルールを定義しています。また、volatileがこれらのルールとどのように対話するかについても説明します。

希望すると便利です。ここで

関連する問題