15

サンプルコード:

class Sample{
    private int v;
    public void setV(){
        Lock a=new Lock();
        a.lock();
        try{
            v=1;
        }finally{
            a.unlock();
        }
    }
    public int getV(){
        return v;
    }
}

スレッドが常に getV を呼び出し、別のスレッドで setV を 1 回だけ実行した場合、その読み取りスレッドは、書き込み直後に新しい値を確認することが保証されていますか? または、「V」を揮発性または AtomicReference にする必要がありますか?

答えが「いいえ」の場合、次のように変更する必要があります。

class Sample{
    private int v;
    private Lock a=new Lock();
    public void setV(){
        a.lock();
        try{
            v=1;
        }finally{
            a.unlock();
        }
    }
    public int getV(){
        a.lock();
        try{
            int r=v;
        }finally{
            a.unlock();
        }
        return r;
    }
}
4

5 に答える 5

10

ドキュメントから:

すべての Lock 実装は、組み込みのモニター ロックによって提供されるものと同じメモリ同期セマンティクスを適用する必要があります。

  • ロック操作の成功は、monitorEnter アクションの成功のように機能します。
  • ロック解除操作の成功は、monitorExit アクションの成功のように機能します。

Lock 両方のスレッド(読み取りスレッドと書き込みスレッド) で使用するとmonitorEnter、キャッシュがフラッシュされるため、読み取りスレッドに新しい値が表示されます。それ以外の場合は、変数を宣言してvolatile、読み取りスレッドでメモリからの読み取りを強制する必要があります。

于 2012-09-14T18:23:52.050 に答える
1

ブライアンの法則に従って...

次に別のスレッドによって読み取られる可能性のある変数を書き込む場合、または別のスレッドによって最後に書き込まれた可能性のある変数を読み取る場合は、同期を使用する必要があり、さらに、リーダーとライターの両方が同じモニター ロックを使用して同期する必要があります。 .

セッターとゲッターの両方を同期させるのが適切でしょう……。

または

ブロックを回避したい場合はAtomicInteger.incrementAndGet()代わりに使用してください(つまり、同期ブロック)lock-unlock

于 2012-09-14T18:20:10.950 に答える
0

volatile または AtomicInteger にする必要があります。これにより、読み取りスレッドが最終的に変更を認識し、ほとんどの目的で「直後」に十分近づくことが保証されます。技術的には、このような単純なアトミック更新には Lock は必要ありません。AtomicInteger の API をよく見てください。set()、compareAndSet() などはすべて、スレッドをアトミ​​ックに読み取ることによって値を可視に設定します。

于 2012-09-14T18:19:50.133 に答える
0

明示的なロック 、synchronizedアトミック参照、およびvolatileはすべて、メモリの可視性を提供します。synchronizedそれらが囲むコードブロックとアトミック参照、およびvolatileそう宣言された特定の変数をロックしてロックします。ただし、可視性が正しく機能するためには、読み取りメソッドと書き込みメソッドの両方を同じロック オブジェクトで保護する必要があります。

あなたのゲッターメソッドはセッターメソッドを保護するロックによって投影されていないため、あなたのケースでは機能しません。変更を加えると、必要に応じて機能します。volatileまた、変数をor AtomicIntegerorとして宣言するだけAtomicReference<Integer>でも機能します。

于 2012-09-14T18:21:59.790 に答える