static
これはすべてのオブジェクトに対して値の 1 つのコピーを意味し、volatile
すべてのスレッドに対して値の 1 つのコピーを意味すると言うのは正しいですか?
いずれにしても、static
変数値はすべてのスレッドに対して 1 つの値になるので、なぜ を選択する必要がありますかvolatile
?
ベストアンサー1
Java で静的変数を宣言すると、クラスのオブジェクトがいくつ作成されても、コピーは 1 つだけになります。変数は、まったくObjects
作成されていなくてもアクセスできます。ただし、スレッドにはローカルにキャッシュされた値が存在する場合があります。
変数がvolatileでstaticでない場合は、 ごとに 1 つの変数が存在しますObject
。そのため、表面的には通常の変数と違いはありませんが、staticとはまったく異なるように見えます。ただし、フィールドがあってもObject
、スレッドは変数値をローカルにキャッシュする場合があります。
つまり、2 つのスレッドが同じオブジェクトの変数を同時に更新し、その変数が volatile として宣言されていない場合、スレッドの 1 つに古い値がキャッシュされている可能性があります。
複数のスレッドを通じて静的な値にアクセスする場合でも、各スレッドはローカルにキャッシュされたコピーを持つことができます。これを回避するには、変数をstatic volatileとして宣言し、これによりスレッドがグローバル値を毎回読み取るように強制します。
ただし、volatile は適切な同期の代替にはなりません。
たとえば、次のようになります。
private static volatile int counter = 0;
private void concurrentMethodWrong() {
counter = counter + 5;
//do something
counter = counter - 5;
}
同時に何度も実行すると、concurrentMethodWrong
カウンターの最終値がゼロと異なる可能性があります。
この問題を解決するには、ロックを実装する必要があります。
private static final Object counterLock = new Object();
private static volatile int counter = 0;
private void concurrentMethodRight() {
synchronized (counterLock) {
counter = counter + 5;
}
//do something
synchronized (counterLock) {
counter = counter - 5;
}
}
または、AtomicInteger
クラス。