2016-10-12 10 views
4

JavaアプリケーションをScalaに移植しようとしています。ダブルバッファから読み取ることとDouble.doubleToRawLongBits(value)がバッファに書き込むDouble.longBitsToDouble(value)の結果を使用して、 - Javaアプリケーションの一部は、フードの下でAtomicLongArrayを使用AtomicDoubleBufferと呼ばれる実装を有しています。私は良いかもしれScalaの実装のためのネットを中心に見てきたと私はthisに上陸揮発性要素の配列を実装する方法

れ、このコードブロック

class VolatileDoubleArray(val length : Int){ 
    val array = new Array[Double](length); 
    @volatile var marker = 0; 
    def apply(i : Int) = {marker; array(i); } 
    def update(i : Int, x : Double) { array(i) = x; marker = 0; } 
} 

は私が起きる前に、保証与えるべきであると述べています。しかし、私はこのことがどうなるか少し混乱しています。 1つの変数上の揮発性マーカーが、前の不揮発性「操作」が成功すると判断する理由は何ですか? JSL 17.4.5の私の解釈は、一つのスレッドでarrayという要素を更新しても、他のスレッドがその更新を見ることを保証するものではないことを示唆しています。何か不足していますか?あるいは、私は起こっていることの全てを混乱させていますか?あなたの例では

答えて

1

この実装は正しい、と保証の前に起こることができます。揮発性変数へ

Becuse 書き込みはが最初にこの揮発性変数を読むことをすべてのスレッドに見えるの書き込みスレッドによって前に作られたすべてのものになります。

この場合、揮発性の「マーカー」変数がメモリバリアのポイントです。

あなたのコード例では

: 「

class VolatileDoubleArray(val length : Int){ 
    val array = new Array[Double](length); 
    @volatile var marker = 0; 
    def apply(i : Int) = {marker; array(i); } 
    def update(i : Int, x : Double) { array(i) = x; marker = 0; } 
} 

あなたはupdateで配列に書き込みをするとき、あなたはまた、それがmarker=0;、 を使用した後とapply内の任意の読み取り前に、揮発性変数右への書き込み配列からは、最初に文marker;だけでvolatile変数を読み込みます。

これにより、アレイへの書き込み(異なるスレッドによって実行される場合もあります)がすべての読み取りに表示されます(この場合、updateが完了した後、applyを実行するスレッドはそれを認識します)。

+0

Hmmはそれを認識していませんでした。しかし、そのコードスニペットでは、 'marker 'が値' 0 'で初期化され、常に同じ値に設定されているので、任意の最適化を実行する任意の自由度でコンパイラではありません。私はわからないが、これはコンパイラが完全に最適化できるもののように見える。あるいは、これは揮発性の変数では違法ですか? – Michael

+1

いいえ、コンパイラは、並行プログラミングに影響を与える可能性のある揮発性変数に対して最適化を実行する自由を持っていません(volatileへの読み書きの副作用がメモリバリアを形成しているため)実行時にそれらのために変更された、それはまさに揮発性変数の目的です。 –

+0

そして、いくつかのポインタのために、私はこれは良い参考です信じて:http://stackoverflow.com/questions/30246007/java-memory-model-volatile-variables-and-happens-before –

関連する問題