プログラミング用語でのデッドロックと競合状態の違いは何ですか?
5 に答える
従来の例を使用して競合状態を考えてください。あなたと友人が同じ銀行口座のATMカードを持っているとしましょう。ここで、アカウントに100ドルが含まれているとします。あなたが$10を引き出しようとし、あなたの友人がまったく同時に$50を引き出しようとしたときに何が起こるかを考えてみてください。
何が起こらなければならないかを考えてください。ATMマシンは、入力を受け取り、現在アカウントにあるものを読み取ってから、金額を変更する必要があります。プログラミング用語では、代入ステートメントは複数のステップからなるプロセスであることに注意してください。
したがって、トランザクションの両方にT1($ 10を引き出す)とT2($ 50を引き出す)の両方にラベルを付けます。さて、左側の以下の数字は時間ステップを表しています。
T1 T2
---------------- ------------------------
1. Read Acct ($100)
2. Read Acct ($100)
3. Write New Amt ($90)
4. Write New Amt ($50)
5. End
6. End
両方のトランザクションが完了した後、このタイムラインを使用します。これは、どのような種類のロックメカニズムも使用しない場合に可能であり、アカウントには$50が含まれています。これは本来よりも10ドル多くなります(トランザクションは永久に失われますが、まだお金はあります)。
これは競合状態と呼ばれます。必要なのは、トランザクションをシリアル化できるようにすることです。つまり、個々の命令の実行をどのようにインターリーブしても、最終結果は、いくつかのシリアルスケジュールとまったく同じになります(つまり、インターリーブなしで次々に実行します)。同じトランザクション。ここでも、解決策はロックを導入することです。ただし、誤ったロックはデッドロックにつながる可能性があります。
デッドロックは、共有リソースの競合がある場合に発生します。それはCatch-22のようなものです。
T1 T2
------- --------
1. Lock(x)
2. Lock(y)
3. Write x=1
4. Write y=19
5. Lock(y)
6. Write y=x+1
7. Lock(x)
8. Write x=y+2
9. Unlock(x)
10. Unlock(x)
11. Unlock(y)
12. Unlock(y)
T2がロックを取得しようとしたx
が、T1はすでにロックを保持しているが、T2が保持x
しているロックを待機しているため、時間7でデッドロックが発生していることがわかりy
ます。
この悪い。この図を依存関係グラフに変えると、サイクルがあることがわかります。ここでの問題は、xとyが一緒に変更される可能性のあるリソースであるということです。
複数のロックオブジェクト(リソース)でこの種のデッドロックの問題を防ぐ1つの方法は、順序付けを導入することです。前の例では、T1がロックされてから、T2がロックされてからが表示x
さy
れy
ますx
。ここで両方のトランザクションが「x
前に常にロックされるy
」という順序付けルールに準拠している場合、この問題は発生しません。(このルールを念頭に置いて前の例を変更すると、デッドロックが発生しないことがわかります)。
これらは些細な例であり、実際には、これについて何らかの学部課程を受講した場合にすでに見た可能性のある例を使用しました。実際には、デッドロックの問題を解決することは、これよりもはるかに難しい場合があります。これは、2つ以上のリソースと2つ以上のトランザクションが相互作用する傾向があるためです。
これが少し役立つことを願っています。いつものように、CSの概念の出発点としてウィキペディアを使用してください。
デッドロックとは、2つ(またはそれ以上)のスレッドが互いにブロックしている場合です。通常、これは共有リソースを取得しようとするスレッドと関係があります。たとえば、スレッドT1とT2が作業を行うために、リソースAとBの両方を取得する必要がある場合です。T1がリソースAを取得すると、T2はリソースBを取得し、T2がリソースAを待機している間、T1はリソースBを待機する可能性があります。この場合、両方のスレッドは、他のスレッドが保持するリソースを無期限に待機します。これらのスレッドはデッドロックしていると言われています。
競合状態は、2つのスレッドが、異なる命令が実行される正確な順序に応じて、否定的な(バギー)方法で相互作用するときに発生します。たとえば、1つのスレッドがグローバル変数を設定し、2番目のスレッドがそのグローバル変数を読み取って変更し、最初のスレッドが変数を読み取る場合、変数が予期せず変更されたため、最初のスレッドでバグが発生する可能性があります。
デッドロック:
- これは、2つ以上のスレッドがリソースを解放するために互いに待機しているときに発生します。
- この場合、スレッドはブロックされた状態にあり、実行されていません。
競合/競合状態:
- これは、2つ以上のスレッドが並行して実行されているが、すべての操作が順番に実行された場合、間違った結果になり、同等ではない場合に発生します。
- ここでは、すべてのスレッドが実行され、そこで操作が実行されます。
コーディングでは、レースとデッドロックの両方の状態を回避する必要があります。
「競合状態」ではなく「競合状態」を意味していると思います(その用語を聞いたことがあります...)
基本的に、デッドロックとは、スレッドAがリソースYのロックを保持しながらリソースXを待機し、スレッドBがリソースXのロックを保持しながらリソースYを待機する状態です。スレッドは互いにブロックして解放します。ロック。
この問題の解決策は、(通常)すべてのスレッドで同じ順序ですべてのリソースを確実にロックすることです。たとえば、リソースYの前に常にリソースXをロックする場合、私の例ではデッドロックが発生することはありません。
競合状態とは、特定の順序で発生する特定の一連のイベントに依存している場合ですが、別のスレッドが同時に実行されていると、混乱する可能性があります。たとえば、リンクリストに新しいノードを挿入するには、リストの先頭を変更する必要があります。通常は次のようになります。
newNode->next = listHead;
listHead = newNode;
しかし、2つのスレッドが同時にそれを行う場合、次のように実行される状況になる可能性があります。
Thread A Thread B
newNode1->next = listHead
newNode2->next = listHead
listHead = newNode2
listHead = newNode1
これが発生した場合、スレッドAがリストを上書きするため、スレッドBによるリストの変更は失われます。正確な状況によってはさらに悪化する可能性がありますが、それが基本です。
この問題の解決策は、通常、適切なロックメカニズムを含めることです(たとえば、リンクリストを変更するときはいつでもロックを解除して、一度に1つのスレッドだけが変更するようにします)。
共有リソースをロックしておらず、複数のスレッドからアクセスされる場合はプログラミング言語に任せて、「競合状態」と呼ばれます。2番目のケースでは、リソースをロックし、共有リソースへのアクセスシーケンスが適切に定義されていない場合、スレッドが長くなる可能性があります。リソースが使用されるのを待ってから、「デッドロック」の場合