マルチスレッド環境での Java 命令の並べ替えを解決する方法
1. はじめに
命令の再配置は、シングルスレッド環境ではプログラムの実行効率の向上に役立ち、プログラムに悪影響を及ぼしませんが、マルチスレッド環境では、命令の再配置は、プログラムに驚きをもたらす、予期しないエラー。
2. 問題の回復
(1) 関連する変数
以下は命令の並び替えを完全に回復できる例です。
public class D { static Integer a; static Boolean flag; public static void writer() { a = 1; flag = true; } public static void reader() { if (flag != null && flag) { System.out.println(a); a = 0; flag = false; } } }
1. 結果予測
reader
メソッドは、flag
変数が true の場合にのみ、変数 a
をコンソールに出力します。価値。
writer
メソッドは、まず変数 a
の代入演算を実行し、次に変数 flag
の代入演算を実行します。
上記の分析ロジックに従う場合、コンソールに出力される結果はすべて 1 である必要があります。
2. 命令の再配置
コードに命令の再配置がない場合、flag
変数が true の場合、変数 a
は 1 でなければなりません。 。
上記のコードでは、変数 a
と変数 flag
に関する両方のメソッド クラスで命令の再配置があります。
public static void writer() { a = 1; flag = true; }
ログ出力を観察すると、多数の 0 出力があることがわかりました。
writer
メソッド内で命令の再配置が発生すると、flag
変数が最初に割り当てを完了します。このとき、現在のスレッドが中断されると、他のスレッドも中断されます。 reader
メソッドを呼び出し、flag
変数が true であることを検出し、変数 a
の値を出力します。この時点で、コンソールには期待値を超える結果が表示されます。
(2) New でオブジェクトを作成します
new キーワードを使用してオブジェクトを作成する場合、非アトミックな操作であるため、命令の再配置が発生します。マルチスレッド環境への影響。
public class Singleton { private static UserModel instance; public static UserModel getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new UserModel(2, "B"); } } } return instance; } } @Data @AllArgsConstructor class UserModel { private Integer userId; private String userName; }
1. 解析と作成のプロセス
キーワード new を使ってオブジェクトを作成するのですが、大まかに次のようなプロセスに分かれます。
## スタック スペースに参照アドレスを作成します。#クラス ファイルをテンプレートとして使用して、ヒープ スペース オブジェクトにメモリを割り当てます。
- #メンバー変数の初期化 #コンストラクターを使用して初期化
- ##参照値を左側の記憶変数に代入
#2. 並べ替えプロセスの分析
上記の例では、最初のスレッドが同期されたコード ブロックに入り、オブジェクトの作成を開始すると仮定します。作成プロセスが中断され、スタック領域に参照アドレスが作成された後、参照値が左側の記憶変数に割り当てられ、その後 CPU スケジューリング タイム スライスの枯渇により割り込みが発生したように見える場合があります。 後続のスレッドで
instance 変数が空ではないことが検出されると、その変数が直接使用されます。シングルトン オブジェクトはインスタンス化されないため、これらを直接使用すると予期しない結果が生じます。
3. 命令の並び替えへの対応
(1) AtomicReference アトミック クラス
アトミック クラスを使用して、その特性を利用して関連する変数のセットをオブジェクトにカプセル化します。アトミックな操作を実現し、コマンドの再配置の問題を効果的に回避します。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>@Data
@NoArgsConstructor
@AllArgsConstructor
public class ValueModel {
private Integer value;
private Boolean flag;
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
アトミック クラスは、マルチスレッド環境で命令を並べ替える場合に推奨されるソリューションです。理解しやすいだけでなく、スレッド間で使用される非ヘビーウェイト ミューテックスは比較的効率的です。
public class E { private static final AtomicReference<ValueModel> ar = new AtomicReference<>(new ValueModel()); public static void writer() { ar.set(new ValueModel(1, true)); } public static void reader() { ValueModel valueModel = ar.get(); if (valueModel.getFlag() != null && valueModel.getFlag()) { System.out.println(valueModel.getValue()); ar.set(new ValueModel(0, false)); } } }
(2) volatile キーワード
public class Singleton { private volatile static UserModel instance; public static UserModel getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new UserModel(2, "B"); } } } return instance; } } @Data @AllArgsConstructor class UserModel { private Integer userId; private String userName; }
4. 命令の再配置についての理解
1. 命令の再配置が広く普及している命令の再配置 配置は整っていないJava プログラムに限定されますが、実際には、ソフトウェアから CPU ハードウェアに至るまで、さまざまなコンパイラで命令の再配置操作が行われます。命令の再配置は、シングル スレッド プログラムのパフォーマンスの最適化です。命令の再配置によって、シングル スレッド環境での順次プログラムの実行で期待される結果が変わるわけではないことは明らかです。
2. マルチスレッド環境での命令の再配置
上記では、2 つの典型的なマルチスレッド環境での命令の再配置について説明し、その悪影響を分析し、それぞれ対策を示しました。
関連する変数の場合は、まずそれらをオブジェクトにカプセル化してから、アトミック クラスを使用して操作します。
新しいオブジェクトの場合は、volatile キーワードを使用しますオブジェクトは、ターゲットを変更できます。
3. 同期ロックは、並べ替えとは何の関係もありません。
同期ロックにより、スレッドが相互接続を通じて順序どおりに特定のコード ブロックにアクセスできるようになります。除外ロック。コード ブロック内のコードは、通常、コンパイラによって実装された戦略に従って並べ替えられます。 同期ロックを使用すると、マルチスレッド環境での並べ替えによる悪影響を回避できますが、ミューテックス ロックによって生じるスレッドのオーバーヘッドが比較的大きいため、お勧めできません。
以上がマルチスレッド環境での Java 命令の並べ替えを解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。
