揮発性キーワードは、Javaマルチスレッドで比較的重要な役割を果たします。揮発性の主な機能は、変数をマルチスレッドで見えるようにすることであり、Javaで提供される最も軽い同期メカニズムです。
可視性
Javaのメモリモデルのすべての変数(ここの変数はローカル変数ではなくグローバル変数です。メソッドが呼び出されるときに変数が破壊されるため、方法にスレッドセーフの問題はありません)はメインメモリに保存されます。各スレッドには独自の作業メモリがあります。スレッドが実行されるたびに、メインメモリから変数のコピーが取得され、変数の動作がスレッドのワーキングメモリで実行されます。異なるスレッドは作業メモリを共有できず、メインメモリから変数のコピーのみを読み取ることができます。具体的には、以下の図で表現できます。
ただし、揮発性の場合(同期/最終的な変更を使用して、上記のルールが壊れます。つまり、スレッドが変数の値を変更すると、他のスレッドが変数の変更をすぐに知ることができます。ただし、スレッドが変数を変更すると、メインメモリに変数を書き留めた後、メインメモリを読み取ります。揮発性によって修正された可変が使用される限り、すべてのスレッドの作業記憶に見えるため、変数はマルチスレッド環境で動作することが保証されていますが、これは一貫していないため、Javaの操作を使用することは原子ではありません。
パブリッククラステスト{private static volatile t = 0; private static int add(){return t ++; } public static void testvolatile(){for(int i = 0; i <20; i ++){thread thread = new thread(() - > {for(int j = 0; j <1000; j ++){add();}}); thread.start(); } while(thread.activecount()> 1){thread.yield(); } system.out.println(t); } public static void main(string [] args){testvolatile(); }}T値は20,000であることが予想されますが、T値が20,000未満の状況があります。理由を推測する必要があります。問題はT ++にあります。 T ++は原子操作ではありません。 Javaでは、T ++操作は最初にt値を取得し、次に1を追加してからtを割り当てることを意味します。 T値を取得すると、揮発性によって変更されるため、スレッドの最新値を取得できます。ただし、1を追加する場合、保証することはできません。他のスレッドがすでに追加されている可能性があります。
では、どのシナリオが揮発性を使用するのに最も適していますか?
*変数操作では現在の値に依存しません
*変数は、他の状態変数との不変制約に参加する必要はありません
中国語に翻訳されているということは、マルチスレッドで読み取りと書き込みの両方を持っている変数の場合、揮発性を使用してそれらを変更できることを意味します。このようにして、読み取り操作にロック/同期操作を使用しないでください。直接読むことは、変数が表示されるためです。