1. ホーム

[解決済み】JavaにおけるVolatileとStaticの比較

2022-04-02 06:23:49

質問

というのは正しいのでしょうか? static はすべてのオブジェクトに対して1つの値のコピーを意味し volatile は、すべてのスレッドに対して1つの値のコピーを意味するのですか?

とにかく static 変数の値もすべてのスレッドで1つの値になるのであれば、なぜ volatile ?

解決方法は?

を宣言することで 静的 Javaでは、クラスのオブジェクトがいくつ作成されても、コピーは1つだけです。この変数は Objects が全く作成されない。しかし、スレッドはその値をローカルにキャッシュしているかもしれません。

ある変数が 揮発性 であって 静的 の場合、各変数に1つの変数が存在します。 Object . つまり、表面上は普通の変数と変わらないように見えますが、実際には 静的 . しかし Object フィールドを使用する場合、スレッドはローカルに変数の値をキャッシュすることができます。

つまり、2つのスレッドが同じオブジェクトの変数を同時に更新し、その変数がvolatileと宣言されていない場合、一方のスレッドが古い値をキャッシュしているケースがあり得るということです。

をアクセスしても 静的 の値を複数のスレッドで使用する場合、各スレッドはローカルにキャッシュされたコピーを持つことができます! これを避けるために、変数を 静的voltaile で、これはスレッドに毎回グローバルな値を読み込ませることになります。

しかし 揮発性 は、適切な同期の代用にはなりません!

例えば、こんな感じです。

private static volatile int counter = 0;

private void concurrentMethodWrong() {
  counter = counter + 5;
  //do something
  counter = counter - 5;
}

実行中 concurrentMethodWrong を同時に何度も実行すると、カウンタの最終的な値が 0 以外になる可能性があります!

この問題を解決するためには、ロックを実装する必要があります。

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 クラスがあります。