static
これは、すべてのオブジェクトに対して値のvolatile
1 つのコピーを意味し、すべてのスレッドに対して値の 1 つのコピーを意味するというのは正しいですか?
とにかく、static
変数値もすべてのスレッドに対して 1 つの値になりvolatile
ます。
static
これは、すべてのオブジェクトに対して値のvolatile
1 つのコピーを意味し、すべてのスレッドに対して値の 1 つのコピーを意味するというのは正しいですか?
とにかく、static
変数値もすべてのスレッドに対して 1 つの値になりvolatile
ます。
Java で静的変数を宣言すると、クラスのオブジェクトがいくつ作成されても、コピーは 1 つだけになります。変数は、まったくObjects
作成されていなくてもアクセスできます。ただし、スレッドはその値をローカルにキャッシュしている場合があります。
変数が静的ではなく揮発性である場合、それぞれに 1 つの変数が存在します。ですから、表面上は通常の変数との違いはないように見えますが、staticとはまったく異なります。ただし、フィールドがある場合でも、スレッドは変数値をローカルにキャッシュする場合があります。Object
Object
これは、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
クラスを使用します。
静的と揮発性の違い:
静的変数: 2 つのスレッド (と仮定t1
)t2
が同じオブジェクトにアクセスし、静的として宣言されている変数を更新している場合、それぞれのキャッシュで同じオブジェクト (静的変数を含む) の独自のローカル コピーを作成できることを意味t1
し、更新します。t2
によって作成されt1
たローカル キャッシュの static 変数は、t2
cache の static 変数に反映されません。
静的変数は、1 つのオブジェクトによって行われた更新が同じクラスの他のすべてのオブジェクトに反映されるObject のコンテキストで使用されますが、静的変数への 1 つのスレッドの更新がすべての変更をすぐに反映するThread のコンテキストでは使用されません。スレッド (ローカルキャッシュ内)。
揮発性変数t1
: 2 つのスレッド (と仮定t2
) が同じオブジェクトにアクセスし、 volatile として宣言されている変数を更新している場合、それは、 volatile として宣言されている変数を除いて、オブジェクトの独自のローカル キャッシュを作成できることを意味t1
します。したがって、volatile 変数にはメイン コピーが 1 つだけあり、それは異なるスレッドによって更新され、あるスレッドによって volatile 変数に対して行われた更新は、すぐに他のスレッドに反映されます。t2
と思いstatic
、volatile
全く関係ありません。Atomic Accessを理解するために Java チュートリアルを読むことをお勧めします。また、Atomic Accessを使用する理由、何がインターリーブされているかを理解すると、答えが見つかります。
volatile 変数値へのアクセスは、メイン メモリから直接行われます。マルチスレッド環境でのみ使用してください。static 変数は 1 回ロードされます。シングルスレッド環境で使用される場合、変数のコピーが更新されても、スレッドが 1 つしかないため、変数にアクセスしても害はありません。
マルチスレッド環境で静的変数が使用されている場合、そこから望ましい結果が期待される場合に問題が発生します。各スレッドには独自のコピーがあるため、あるスレッドからの静的変数の増分または減分は、別のスレッドに反映されない場合があります。
静的変数から望ましい結果が期待される場合は、マルチスレッドで静的で揮発性を使用すると、すべてが解決されます。
変数を静的として宣言すると、変数のコピーは 1 つだけになります。そのため、異なるスレッドがその変数にアクセスするたびに、変数の最終値は 1 つだけになります (変数に割り当てられるメモリ位置は 1 つだけであるため)。
変数が揮発性として宣言されている場合、すべてのスレッドは変数の独自のコピーを持ちますが、値はメイン メモリから取得されます。そのため、すべてのスレッドの変数の値は同じになります。
したがって、どちらの場合も、主なポイントは、変数の値がすべてのスレッドで同じであるということです。