282

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

とにかく、static変数値もすべてのスレッドに対して 1 つの値になりvolatileます。

4

8 に答える 8

385

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

変数が静的ではなく揮発性である場合、それぞれに 1 つの変数が存在します。ですから、表面上は通常の変数との違いはないように見えますが、staticとはまったく異なります。ただし、フィールドがある場合でも、スレッドは変数値をローカルにキャッシュする場合があります。ObjectObject

これは、2 つのスレッドが同じオブジェクトの変数を同時に更新し、その変数が volatile と宣言されていない場合、スレッドの 1 つが古い値をキャッシュに保持している場合があることを意味します。

複数のスレッドを介して静的な値にアクセスする場合でも、各スレッドはローカルにキャッシュされたコピーを持つことができます! これを回避するには、変数をstatic volatileとして宣言すると、グローバル値のたびにスレッドが強制的に読み取られます。

ただし、揮発性は適切な同期の代わりにはなりません!
例えば:

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クラスを使用します。

于 2011-10-30T05:29:08.027 に答える
294

静的と揮発性の違い:

静的変数: 2 つのスレッド (と仮定t1)t2が同じオブジェクトにアクセスし、静的として宣言されている変数を更新している場合、それぞれのキャッシュで同じオブジェクト (静的変数を含む) の独自のローカル コピーを作成できることを意味t1し、更新します。t2によって作成されt1たローカル キャッシュの static 変数は、t2cache の static 変数に反映されません。

静的変数は、1 つのオブジェクトによって行われた更新が同じクラスの他のすべてのオブジェクトに反映されるObject のコンテキストで使用されますが、静的変数への 1 つのスレッドの更新がすべての変更をすぐに反映するThread のコンテキストでは使用されません。スレッド (ローカルキャッシュ内)。

揮発性変数t1: 2 つのスレッド (と仮定t2) が同じオブジェクトにアクセスし、 volatile として宣言されている変数を更新している場合、それは、 volatile として宣言されている変数を除いて、オブジェクトの独自のローカル キャッシュを作成できることを意味t1します。したがって、volatile 変数にはメイン コピーが 1 つだけあり、それは異なるスレッドによって更新され、あるスレッドによって volatile 変数に対して行われた更新は、すぐに他のスレッドに反映されます。t2

于 2012-08-30T09:38:06.817 に答える
5

と思いstaticvolatile全く関係ありません。Atomic Accessを理解するために Java チュートリアルを読むことをお勧めします。また、Atomic Accessを使用する理由、何がインターリーブされているかを理解すると、答えが見つかります。

于 2013-08-25T06:06:15.527 に答える
0

volatile 変数値へのアクセスは、メイン メモリから直接行われます。マルチスレッド環境でのみ使用してください。static 変数は 1 回ロードされます。シングルスレッド環境で使用される場合、変数のコピーが更新されても、スレッドが 1 つしかないため、変数にアクセスしても害はありません。

マルチスレッド環境で静的変数が使用されている場合、そこから望ましい結果が期待される場合に問題が発生します。各スレッドには独自のコピーがあるため、あるスレッドからの静的変数の増分または減分は、別のスレッドに反映されない場合があります。

静的変数から望ましい結果が期待される場合は、マルチスレッドで静的で揮発性を使用すると、すべてが解決されます。

于 2017-03-27T07:15:32.530 に答える
-2

変数を静的として宣言すると、変数のコピーは 1 つだけになります。そのため、異なるスレッドがその変数にアクセスするたびに、変数の最終値は 1 つだけになります (変数に割り当てられるメモリ位置は 1 つだけであるため)。

変数が揮発性として宣言されている場合、すべてのスレッドは変数の独自のコピーを持ちますが、値はメイン メモリから取得されます。そのため、すべてのスレッドの変数の値は同じになります。

したがって、どちらの場合も、主なポイントは、変数の値がすべてのスレッドで同じであるということです。

于 2011-04-20T06:04:22.853 に答える