競合状態やデッドロックの説明

概要

Visual Basic .NET または Visual Basic 2005年には、最初に Visual Basic アプリケーションでスレッドを使用する機能が用意されています。スレッドでは、競合状態やデッドロックなどのデバッグの問題について説明します。この資料では、これら 2 つの問題について説明します。

詳細

競合状態

競合状態は、2 つのスレッドを同時に共有変数にアクセスするときに発生します。最初のスレッドは、変数を読み取り、2 番目のスレッドは、変数の同じ値を読み取ります。最初のスレッドと 2 番目のスレッドの値に操作を実行するとして、どのスレッドが共有変数に値を最後書き込むことができます、競合します。値の値の書き込みを行うスレッドの最後は予約されて、スレッドの値を書き込みは前のスレッドを作成するためです。

詳細と例

各スレッドは、プロセッサで実行するのにはあらかじめ定義された期間に割り当てられます。スレッドに割り当てられる時間が経過すると、プロセッサ上の次のターンまで、スレッドのコンテキストを保存し、プロセッサは、次のスレッドの実行を開始します。

1 行のコマンドで競合状態が発生ことができますか競合状態の発生を確認する次の使用例を確認します。2 つのスレッドが存在し、合計と呼ばれる共有の変数を更新している両方 (として表されますが、 dword ptr ds: [031B49DCh]のアセンブリ コードで)。

Visual Basic のコード:
   'Thread 1   Total = Total + val1

   'Thread 2   Total = Total - val2

上記の Visual Basic コードのコンパイル (行番号) を持つアセンブリ コード。
 'Thread 1 1.   mov         eax,dword ptr ds:[031B49DCh] 
2. add eax,edi
3. jno 00000033
4. xor ecx,ecx
5. call 7611097F
6. mov dword ptr ds:[031B49DCh],eax

 'Thread 2 1.   mov         eax,dword ptr ds:[031B49DCh] 
2. sub eax,edi
3. jno 00000033
4. xor ecx,ecx
5. call 76110BE7
6. mov dword ptr ds:[031B49DCh],eax

アセンブリ コードを見ると、操作の回数を確認できます、プロセッサの実行時に簡単な加算を実行するために下位のレベルです。スレッドは、プロセッサの時間の中に、アセンブリ コードの一部またはすべてを実行できる場合があります。このコードからの競合状態の発生になります。

合計値が 100、val1 50、val2 15。スレッド 1 を実行する機会を取得しますが、1 ~ 3 の手順を完了するだけです。つまり、スレッド 1 は、変数を読み取るし、追加が完了します。スレッド 1 だけするを待って 150 の新しい値を記述します。1 のスレッドを停止すると、スレッド 2 は完全に実行するために取得します。つまり、それが書き込まれる値に計算されること (85) を変数の合計値になります。最後に、スレッド 1 は、コントロールを取り戻すし、実行を終了します。それは、その値 (150) を書き込みます。したがって、スレッドの 1 が完了したら、合計の値が、85 の代わりに 150。


このような方法についてを参照してください大きな問題です。これが・ バンキング ・ プログラムの場合、顧客は存在すべき自分のアカウントにお金があります。


このエラーがランダムには、プロセッサの期限が切れるし、スレッド 2 が実行を開始し、スレッドの 1 にその時刻より前に処理が完了する可能性があるためです。これらのイベントが発生した場合、問題は発生しません。 スレッドの実行が非決定的で、時間と実行の順序を制御できないためです。スレッドがデバッグ モードと実行時に異なる方法で実行可能性があることにも注意してください。その系列の各スレッドを実行する場合、エラーが発生しないかを確認できます。この乱数は、これらのエラーを追跡し、デバッグがはるかに困難になります。


競合状態が発生しないようにするのには、一度に 1 つだけのスレッドが共有変数へのアクセスを持つように共有変数をロックできます。多用せず、変数を解放するスレッドの 1 の 2 のスレッドが待機中に変数が 1 のスレッドにロックされている、スレッド 2 は変数も必要な場合は、スレッド 2 の実行を停止するためです。(詳細については、この資料の「関連情報」セクションでは、「SyncLock」を参照してください)。

現象

競合状態の最も一般的な現象は、複数のスレッド間で共有される変数の予測値です。これは、スレッドが実行される順序の不確実性に起因します。いずれかの時点のスレッドを 1 つの wins およびいずれかの時点のスレッドまたはほかの wins。時以外にも、実行は正しく動作します。また、各スレッドを別々 に実行する場合、変数の値は正しく動作します。


デッドロック

デッドロックは、2 つのスレッドそれぞれを同時に、別の変数をロックし、他のスレッドが既にロックされている変数をロックしようとするは、ときに発生します。その結果、各スレッドは、実行が停止され、変数を解放するその他のスレッドを待機します。各スレッドが他のスレッドが、何も問題が発生すると、変数を保持しているため、スレッドはデッドロック状態のまま。

詳細と例

次のコードには、LeftVal と RightVal の 2 つのオブジェクトがあります。

'Thread 1SyncLock LeftVal
SyncLock RightVal
'Perform operations on LeftVal and RightVal that require read and write.
End SyncLock
End SyncLock

'Thread 2SyncLock RightVal
SyncLock LeftVal
'Perform operations on RightVal and LeftVal that require read and write.
End SyncLock
End SyncLock

デッドロックは、スレッド 1 は、LeftVal をロックするのには許可されている場合に発生します。プロセッサでは、スレッドの 1 の実行を停止し、2 のスレッドの実行を開始します。スレッド 2 RightVal をロックし、LeftVal をロックしようとします。LeftVal がロックされているため、スレッド 2 は停止し、LeftVal を解放するまで待機します。2 のスレッドが停止しているために、実行を続行するのにはスレッドの 1 が許可されます。スレッド 1 は RightVal をロックしようとしていますが、できません、スレッド 2 がロックされているためです。その結果、スレッド 1 は RightVal が使用可能になるまで待機する起動します。各スレッドが他のスレッドが待機している変数をロックしているため、他のスレッドの各スレッドが待機して、どちらのスレッドがロックを解除することを保持する変数です。


デッドロックは、常に発生しません。スレッド 1 は、プロセッサが停止する前に両方のロックを実行する場合、スレッド 1 はその操作を実行し、共有変数のロックを解除し、できます。スレッド 1、変数のロックを解除後、は、期待どおりに実行、スレッド 2 が続行できます。


このエラーは、これらのスニペットのコードが横に並べて配置されますが、実際には、個別のモジュールや、コードの領域にコードが表示されることは明らかでしょう。この起こり得るため、この同じコードでは、正しく実行し、不正な実行を追跡するのには非常に難しいエラーです。

現象

デッドロックの一般的な現象では、1 つまたは複数のスレッドが応答を停止します。これは、ハングとも呼ばれます。少なくとも 2 つのスレッドは、他のスレッドがロックされている変数のそれぞれの待機中です。スレッドの操作を行うために続行できません、他の変数を取得するまでにどちらのスレッドがその変数をリリースします。全体のプログラムは、実行の完了が、それらのスレッドの一方または両方のプログラムが待機している場合にハングします。

スレッドとは何ですか。

プロセスを使用して、指定された 1 台のコンピューター上で実行している別のアプリケーションを分離します。オペレーティング システム プロセスは実行されませんが、スレッドの操作を行います。スレッドは、実行の単位です。オペレーティング システムでは、スレッドのタスクを実行するためのスレッドにプロセッサ時間を割り当てます。1 つのプロセスでは、複数の実行スレッドを含めることができます。各スレッドは、独自の例外ハンドラー、スケジューリングの優先順位、スレッドがプロセッサに割り当てられていたときにその実行を完了できない場合は、スレッドのコンテキストを保存するのにはオペレーティング システムが使用される構造体のセットを保持します。コンテキストは、次のスレッドがプロセッサ時間を受信するまで保持されます。コンテキストには、スレッドがシームレスに実行を続行する必要があるすべての情報が含まれています。この情報には、プロセッサのレジスタとホスト プロセスのアドレス空間内の呼び出しスタックのスレッドのセットが含まれています。

関連情報

詳細については、次のキーワードに対する Visual Studio のヘルプを検索します。
  • SyncLock。ロックするオブジェクトを使用できます。別のスレッドが同じオブジェクトをロックしようとすると、最初のスレッドを解放するまでブロックされます。SyncLock の誤用の問題につながるため、慎重に SyncLock を使用します。たとえば、このコマンドは、競合状態を防ぐため、デッドロックが発生します。
  • インター ロックします。選択された一連の基本的な数値変数にスレッド セーフな操作を使用できます。
詳細については、マイクロソフト サポート技術情報の記事を表示するのには以下の記事番号をクリックします。

316422 INFO: Visual Basic .NET におけるスレッド処理のためのロードマップ
詳細については、次の MSDN Web サイトを参照してください。
プロパティ

文書番号:317723 - 最終更新日: 2017/02/01 - リビジョン: 1

Microsoft Visual Basic 2005, Microsoft Visual Basic .NET 2003 Standard Edition, Microsoft Visual Basic .NET 2002 Standard Edition

フィードバック