ホームページ >Java >&#&チュートリアル >Java における synchronized と volatile の違いと関係
この記事では主に Java の volatile と synchronized の違いと関連性について説明します。この記事がこの部分の内容を理解するのに役立つことを願っています。必要な方は
Java の volatile と synchronized の違いと同期を参照してください。接続
これはおそらく、揮発性と同期の効果を比較した最良の記事です。 Volatile は変数修飾子であり、synchronized はメソッドまたはブロック修飾子です。したがって、これら 2 つのキーワードを使用して、変数にアクセスする 3 つの簡単な方法
int i1; int geti1() {return i1;} volatile int i2; int geti2() {return i2;} int i3; synchronized int geti3() {return i3;}
geti1() を指定し、現在のスレッドの i1 変数の値を即座に取得します。スレッドは変数のローカル コピーを取得できますが、取得された変数の値は、他のスレッドによって取得された値と必ずしも同じではありません。特に、他のスレッドが i1 の値を変更した場合、現在のスレッドによって取得された i1 の値は変更された値と異なる可能性があります。実際、Java には、メイン メモリを使用して変数の現在の正しい値を保存するメイン メモリ メカニズムがあります。スレッドは変数の値を独自の独立したメモリにコピーしますが、これらのスレッドのメモリ コピーはメイン メモリ内の値と異なる場合があります。したがって、実際には、メイン メモリ内の i1 の値が 1 で、スレッド 1 とスレッド 2 の両方が i1 を変更したにもかかわらず、更新された値がメイン メモリまたは他のスレッドに転送されていないことが発生する可能性があります。スレッドに存在する スレッド 1 の i1 の値は 2 ですが、スレッド 2 の i1 の値は 3 です。
一方、geti2() はメインメモリから i2 の値を効果的に取得できます。揮発性変数では、スレッドが変数の値をメイン メモリから独自の記憶領域にコピーすることはできません。したがって、volatile として宣言された変数は、どのスレッドで変数を変更しても、他のスレッドはすぐに同じ結果を取得します。スレッドが自身のデータ コピーにアクセスしたり変更したりする方が効率的であるため、volatile 型変数はパフォーマンスをある程度消費します。
では、揮発性変数がすでにスレッド間でデータを同期できる場合、同期は何に使用されるのでしょうか?両者には 2 つの違いがあります。まず、同期はリスナーによって制御されるロックを取得および解放します。2 つのスレッドがリスナー (つまり、同じオブジェクト ロック) を使用する場合、リスナーは一度に 1 つのスレッドのみにコード ブロックの処理を強制できます。これが最も一般的です。同期します。さらに、同期ではメモリも同期できます。実際には、synchronized により、すべてのスレッド メモリがメイン メモリと同期されます。 geti3() の実行プロセスは次のようになります:
1. スレッドはリスナーからオブジェクトのロックを取得します。 (ここではリスナーがロックされていないと仮定しています。そうでない場合、スレッドはリスナーがロック解除されるまでしかオブジェクトのロックを取得できません)
2. スレッドのメモリはすべての変数を更新します。これは、メインの変数を読み取ることを意味します。メモリ自体の変数が有効であることを確認します。 (JVM は「ダーティ」フラグを使用して、「ダーティ」フラグを持つ変数のみが更新されるようにプロセスを最適化します。詳細については、JAVA 仕様の 17.9 を参照してください)
3. コード ブロックが実行されます。例: set 戻り値は、メイン メモリからリセットされたばかりの i3 の現在値です。)
4. 変数への変更はメイン メモリに書き戻されます。ただし、この例では geti3() に変更はありません。
5. スレッドはオブジェクトのロックをリスナーに解放します。
つまり、volatile はスレッド メモリとメイン メモリの間で 1 つの変数の値のみを同期できますが、synchronized はスレッド メモリとメイン メモリの間ですべての変数の値を同期し、リスナーをロックして解放することでこれを実現します。明らかに、同期型は揮発型よりもパフォーマンスが高くなります。
2 つの違いについて
1. Volatile は基本的に、レジスタ (作業メモリ) 内の現在の変数の値が不確実であり、現在の変数を同期して読み取る必要があることを JVM に伝えます。変数 、現在のスレッドのみがこの変数にアクセスでき、他のスレッドはブロックされます。
2.volatile は変数レベルでのみ使用できます。synchronized は変数、メソッド、クラス レベルで使用できます
3.volatile は変数の変更の可視性のみを実現し、アトミック性を保証できません; synchronized そうすると、変数変更の可視性と原子性が保証されます
4. Volatile はスレッドのブロックを引き起こしません。synchronized はスレッドのブロックを引き起こす可能性があります。
5. volatile とマークされた変数はコンパイラによって最適化されません; synchronized とマークされた変数はコンパイラによって最適化できます
赤色のフォント部分の理由は次のとおりです:
スレッド A が変数を変更する場合まだ終了していません。Volatile 変数はロックされていないため、別のスレッド B は変更された値を確認でき、A がロックを解放するのを待たずにこの変数を変更できます
以上がJava における synchronized と volatile の違いと関係の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。