JAVA言語でダブルチェックロックを解析する方法
1. ロックの二重チェック
プログラム開発では、高コストのオブジェクトの初期化操作を延期し、これらのオブジェクトが使用されるときにのみ初期化する必要がある場合があります。を使用すると、二重チェック ロックを使用してオブジェクトの初期化操作を遅らせることができます。ダブルチェック ロックは、同時実行システムにおける競合と同期のオーバーヘッドを軽減するために設計されたソフトウェア設計パターンです。通常のシングルトン パターンに基づいて、最初にオブジェクトが初期化されているかどうかを判断し、次にそれをロックするかどうかを決定します。二重チェックされたロックは、マルチスレッド環境における通常のシングルトン パターンのエラーが発生しやすくスレッドセーフでない問題を解決しますが、依然としていくつかの隠れた危険性があります。以下では、JAVA 言語のソース コードを例として、ダブルチェック ロックの欠陥の原因と修復方法を分析します。
2. ダブル チェック ロック危険
ダブル チェック ロックは、シングル スレッド環境では影響しません。スレッドはいつでも実行を切り替えるため、命令が再配置されるとオブジェクトが完全にインスタンス化されず、プログラム呼び出しエラーが発生します。
3. サンプル コード
この例は、Samate Juliet Test Suite for Java v1.3 (https://samate.nist.gov/SARD/testsuite. php )、ソース ファイル名: CWE609_Double_Checked_Locking__Servlet_01.java。
3.1 欠陥コード
上記のコード行は 23 ~ 38 です。プログラムはまず、stringBad## かどうかを判断します。 # null の場合、そうでない場合は、
String オブジェクトが直接返されるため、
synchronized ブロックに入るために必要なリソースが回避されます。
synchronized キーワードを使用すると、
stringBad が null の場合にマルチスレッド環境で
String オブジェクトが複数作成されることを回避できます。実際にコードを実行すると、上記のコードでもエラーが発生する可能性があります。
stringBad オブジェクトの作成と代入操作が 2 つのステップで実行されます。ただし、JVM はこれら 2 つの操作の順序を保証しません。命令が並べ替えられると、JVM はまずメモリ アドレスを指す値を割り当て、次に
stringBad オブジェクトを初期化します。この時点で 2 つのスレッドがある場合、両方のスレッドが同時に 27 行目に入ります。スレッド 1 は最初に
synchronized ブロックに入り、
stringBad が null であるため、33 行目を実行します。 JVM が命令を並べ替えるとき、JVM はまずインスタンスの空のメモリを割り当てて
stringBad に割り当てますが、この時点では
stringBad オブジェクトはまだインスタンス化されていません。スレッド 1 は
synchronized ブロックを残しました。スレッド 2 が
synchronized ブロックに入ると、この時点では
stringBad が null ではないため、インスタンス化されていないオブジェクトが直接返されます (メモリ アドレス値のみで、オブジェクトは実際には初期化されません)。後続のスレッド 2 が
stringBad オブジェクトを操作するプログラムを呼び出すと、この時点のオブジェクトは初期化されていないため、エラーが発生します。
#図 1: 「Double Check Lock」の検出例
#
上記の修復コードでは、23 行目の volatile
キーワードを使用して、シングルトン変数 stringBad
を変更します。 volatile
命令キーワードとして、コンパイラの最適化によって命令が省略されないようにし、毎回値を直接読み取る必要があります。
コンパイラの最適化により、コードの実際の実行は、記述した順序と異なる場合があります。コンパイラは、プログラムの実行結果がソースコードと同じであることを保証するだけで、実際の命令の順序がソースコードと同じであることは保証しないため、シングルスレッド環境では問題ありません。マルチスレッド環境を導入すると、この種の障害が深刻な問題を引き起こす可能性があります。 volatile
キーワードはこの問題を意味的に解決できますが、volatile
の命令並べ替え最適化機能の禁止は Java 1.5 でのみ実装されたため、1.5 より前のバージョンはまだ残っていることに注意してください。 volatile
キーワードが使用されている場合でも、安全ではありません。
360 コード ガードを使用して修復されたコードを検出すると、「ダブル チェック ロック」欠陥が存在しないことがわかります。図 2 に示すように:
4、二重チェック ロックを回避する方法
二重チェック ロックを回避するには、次の点に注意する必要があります。 (1) volatile キーワードを使用して命令の並べ替えを回避しますが、このソリューションには JDK5 以降が必要です。これは、JDK5 から使用されるためです。新しい JSR-133 メモリ モデル仕様は、volatile のセマンティクスを強化します。 (2) クラスの初期化に基づく解決策。JVM は、クラスの初期化フェーズ中 (つまり、クラスがロードされた後、スレッドによって使用される前) にクラスの初期化を実行します。実行クラスの初期化中に、JVM はロックを取得します。このロックは、複数のスレッドによる同じクラスの初期化を同期できます。
以上が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 の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

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

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

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

カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4

Spring Bootは、Java開発に革命をもたらす堅牢でスケーラブルな、生産対応のJavaアプリケーションの作成を簡素化します。 スプリングエコシステムに固有の「構成に関する慣習」アプローチは、手動のセットアップを最小化します。
