プログラム開発では、高コストのオブジェクトの初期化操作を延期し、これらのオブジェクトが使用されるときにのみ初期化する必要がある場合があります。を使用すると、二重チェック ロックを使用してオブジェクトの初期化操作を遅らせることができます。ダブルチェック ロックは、同時実行システムにおける競合と同期のオーバーヘッドを軽減するために設計されたソフトウェア設計パターンです。通常のシングルトン パターンに基づいて、最初にオブジェクトが初期化されているかどうかを判断し、次にそれをロックするかどうかを決定します。二重チェックされたロックは、マルチスレッド環境における通常のシングルトン パターンのエラーが発生しやすくスレッドセーフでない問題を解決しますが、依然としていくつかの隠れた危険性があります。以下では、JAVA 言語のソース コードを例として、ダブルチェック ロックの欠陥の原因と修復方法を分析します。
ダブル チェック ロックは、シングル スレッド環境では影響しません。スレッドはいつでも実行を切り替えるため、命令が再配置されるとオブジェクトが完全にインスタンス化されず、プログラム呼び出しエラーが発生します。
この例は、Samate Juliet Test Suite for Java v1.3 (https://samate.nist.gov/SARD/testsuite. php )、ソース ファイル名: CWE609_Double_Checked_Locking__Servlet_01.java。
上記のコード行は 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」の検出例
#
volatile
キーワードを使用して、シングルトン変数 stringBad
を変更します。 volatile
命令キーワードとして、コンパイラの最適化によって命令が省略されないようにし、毎回値を直接読み取る必要があります。 volatile
キーワードはこの問題を意味的に解決できますが、volatile
の命令並べ替え最適化機能の禁止は Java 1.5 でのみ実装されたため、1.5 より前のバージョンはまだ残っていることに注意してください。 volatile
キーワードが使用されている場合でも、安全ではありません。 360 コード ガードを使用して修復されたコードを検出すると、「ダブル チェック ロック」欠陥が存在しないことがわかります。図 2 に示すように:
JVM は、クラスの初期化フェーズ中 (つまり、クラスがロードされた後、スレッドによって使用される前) にクラスの初期化を実行します。実行クラスの初期化中に、JVM はロックを取得します。このロックは、複数のスレッドによる同じクラスの初期化を同期できます。
以上がJAVA言語でダブルチェックロックを解析する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。