3

単一のスレッドでのみ更新される一連のカウンターがあります。

これらの値を別のスレッドから読み取り、volatile/atomic/synchronized を使用していない場合、これらの値はどれくらい古くなる可能性がありますか?

ここで volatile/atomic/synchronized の使用を避けることができるかどうか疑問に思っているので質問します。

私は現在、更新の時間について何の仮定もできないと考えています (そのため、少なくとも volatile を使用せざるを得ません)。ここで何かが欠けていないことを確認したいだけです。

4

4 に答える 4

4

ここで volatile/atomic/synchronized の使用を避けることができるかどうか疑問に思っているので質問します。

実際には、CPU キャッシュはおそらく定期的にメイン メモリに同期されます (頻度は多くのパラメーターに依存します)。

しかし、それは要点を欠いています。実際の問題は、適切な同期パターンを使用しない場合、コンパイラが自由にコードを「最適化」して更新部分を削除できることです。

例えば:

class Broken {
    boolean stop = false;

    void broken() throws Exception {
        while (!stop) {
            Thread.sleep(100);
        }
    }
}

コンパイラは、そのコードを次のように書き換えることが許可されています。

void broken() throws Exception {
    while (true) {
        Thread.sleep(100);
    }
}

メソッドstopの実行中に不揮発性が変更される可能性があるかどうかを確認する義務がないためです。変数を としてbrokenマークし、その最適化はこれ以上許可されません。stopvolatile

結論: 状態を共有する必要がある場合は、同期が必要です。

于 2013-05-09T22:21:03.260 に答える
4

値がどの程度古くなるかは、完全に実装の裁量に任されています。仕様では保証されていません。特定の JVM の実装の詳細に依存し、メモリ モデルまたは JIT によるコードの並べ替え方法の変更によって破損する可能性があるコードを記述します。仕様は、volatile、final、synchronized などによって課される制約を遵守する限り、実装者が望むだけのロープを提供することを意図して書かれているようです。

于 2013-05-09T21:12:20.057 に答える
0

Java8 には、フィールドで volatile を使用する際の問題を解決する LongAdder という新しいクラスがあります。でもそれまでは…

カウンターで volatile を使用しない場合、結果は予測できません。volatile を使用すると、各書き込みでキャッシュ/メモリの一貫性を保証する必要があるため、パフォーマンスの問題が発生します。多くのスレッドが頻繁に書き込みを行う場合、これは大きなパフォーマンスの問題です。

アプリケーションにとって重要ではない統計とカウンターについては、ユーザーに volatile/atomic または none のオプションを提供し、デフォルトは none にします。これまでのところ、ほとんどは何も使用していません。

于 2013-05-10T13:30:41.770 に答える