Java揮発性キーワード
Java Thread Concurrency Processingでは、キーワードの揮発性の使用には多くの混乱があります。このキーワードを使用すると、マルチスレッドの並行性処理を使用すると、すべてがうまく機能する可能性があると思います。
Java言語はマルチスレッドをサポートしています。スレッドの同時性の問題を解決するために、言語内に同期ブロックと揮発性キーワードメカニズムが導入されます。
同期
誰もが同期ブロックに精通しており、同期されたキーワードを介して実装されます。同期されたステートメントとブロックステートメントを使用すると、マルチスレッドにアクセスするときに同時に使用できるスレッドは1つだけです。
同期された変更されたメソッドまたはコードブロック。
揮発性
揮発性で変更された変数の場合、スレッドは変数を使用するたびに変数の最も変更された値を読み取ります。揮発性は簡単に誤用され、原子動作に使用されます。
以下の例を見てみましょう。カウンターを実装します。スレッドが始まるたびに、カウンターINCメソッドが呼び出され、カウンターに追加されます。
実行環境-JDKバージョン:JDK1.6.0_31、メモリ:3G CPU:X86 2.4G
パブリッククラスカウンター{public static int count = 0; public static void inc(){//ここでの遅延は1ミリ秒です。 } catch(arternedexception e){} count ++; } public static void main(string [] args){//同時に1000スレッドを開始してi ++計算を実行し、(int i = 0; i <1000; i ++){new runnable(){@Override public void run(){counter.inc();}) } //ここでの各実行の値は異なる場合があり、おそらく1000 system.out.println( "run result:counter.count =" + counter.count); }}运行结果:Counter.count= 995
实际运算结果每次可能都不一样,本机的结果为:运行结果:Counter.count= 995 ,可以看出,在多线程的环境下,Counter.count并没有期望结果是1000
多くの人々は、これがマルチスレッドの並行性の問題であると考えています。この問題を回避するために、很多人以为,这个是多线程并发问题,只需要在变量count之前加上volatileを追加するだけです就可以避免这个问题,那我们在修改代码看看,看看结果是不是符合我们的期望
public class counter {public volatile static int count = 0; public static void inc(){//ここでの遅延は1ミリ秒です。 } catch(arternedexception e){} count ++; } public static void main(string [] args){//同時に1000スレッドを開始し、i ++計算を実行し、(int i = 0; i <1000; i ++){new runnable(){@override public void run(){counter.inc();}) } //ここでの各実行の値は異なる場合があります。 }}実行結果:Counter.Count = 992
操作の結果は、予想されるほど1000ではありません。以下の理由を分析しましょう
Java Garbage Collectionの記事では、JVMの瞬間にメモリの割り当てが説明されています。メモリ領域の1つはJVM仮想マシンスタックで、各スレッドには実行時にスレッドスタックがあります。
スレッドスタックは、スレッドランタイム中に変数値情報を保存します。スレッドが特定のオブジェクトの値にアクセスしたら、最初にオブジェクトの参照を介してヒープメモリに対応する変数の値を見つけてから、ヒープメモリを配置します
変数の特定の値はスレッドのローカルメモリにロードされ、変数のコピーが作成されます。その後、スレッドはヒープメモリ内のオブジェクトの変数値と関係がありませんが、コピー変数の値を直接変更します。
変更後の特定の瞬間(スレッドが終了する前)、スレッド変数コピーの値は、ヒープ内のオブジェクト変数に自動的に書き戻されます。このようにして、ヒープ内のオブジェクトの値が変わります。次の写真
このライティングの相互作用を説明してください
メインメモリから現在のワーキングメモリまでの変数を読み取り、ロードします
実行コードを使用して割り当てて共有変数値を変更します
ワーキングメモリデータでメインメモリ関連のコンテンツをリフレッシュして書き留める
使用と割り当ては複数回表示できます
ただし、これらの操作は原子ではありません。つまり、読み取り負荷後、メインメモリカウント変数が変更された場合、スレッドワーキングメモリの値はロードされているため、対応する変更を引き起こさないため、計算された結果は予想とは異なります。
揮発性によって変更された変数の場合、JVM仮想マシンは、メインメモリからスレッドワーキングメモリにロードされた値が最新であることのみを保証します
たとえば、スレッド1とスレッド2が読み取り操作とロード操作を実行し、メインメモリのカウント値が5であることがわかった場合、最新の値はロードされます
ヒープカウントがスレッド1で変更されると、メインメモリに書き込まれ、メインメモリのカウント変数は6になります。
Thread 2はすでに読み取りおよび負荷操作を実行しているため、メインメモリカウントの変動値も操作後6に更新されます。
これにより、2つのスレッドが時間内に揮発性キーワードで変更された後、同時性が発生します。
読んでくれてありがとう、私はそれがあなたを助けることができることを願っています。このサイトへのご支援ありがとうございます!