プログラミング用語でのデッドロックと競合状態との違いは何ですか?
従来の例を使用して競合状態を考えます。あなたと友人が同じ銀行口座の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ドル多くなります(トランザクションは永久に失われますが、お金は残っています)。
これは、競合状態と呼ばれます。必要なのは、トランザクションがserializableであることです。つまり、どのように個々の命令の実行をインターリーブしても、最終結果はまったく同じになります。 assome同じトランザクションのシリアルスケジュール(インターリーブなしで次々に実行することを意味します)。ここでも、解決策はロックを導入することです。ただし、誤ったロックはデッドロックにつながる可能性があります。
共有リソースの競合がある場合、デッドロックが発生します。キャッチ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はすでにx
のロックを保持しているが、T2が保持するy
のロックを待機しているため、デッドロックが時間7に発生することがわかります。
この悪い。この図を依存関係グラフに変えると、サイクルがあることがわかります。ここでの問題は、xとyが一緒に変更される可能性があるリソースであるということです。
複数のロックオブジェクト(リソース)でこの種のデッドロックの問題を防ぐ1つの方法は、順序付けを導入することです。前の例では、T1はx
をロックしてからy
をロックしましたが、T2はy
をロックしてからx
をロックしました。両方のトランザクションが、「x
が常にy
の前にロックされる」という順序規則に従っている場合、この問題は発生しません。 (このルールを念頭に置いて前の例を変更すると、デッドロックが発生しないことがわかります)。
これらはささいな例であり、実際に私はあなたがこれについて何らかの学部課程を受講した場合にあなたがすでに見たかもしれない例を使用した。現実には、デッドロックの問題を解決するのはこれよりもはるかに難しい場合があります。これは、2つ以上のリソースと相互作用する2つ以上のトランザクションがあるためです。
これが少し役立つことを願っています。いつものように、CSの概念の出発点としてウィキペディアを使用します。
デッドロックは、2つ(またはそれ以上)のスレッドが互いにブロックしている場合です。通常、これはスレッドが共有リソースを獲得しようとすることと関係があります。たとえば、スレッドT1とT2が作業を行うためにリソースAとBの両方を取得する必要がある場合。 T1がリソースAを取得すると、T2はリソースBを取得し、T1はリソースBを待機し、T2はリソースAを待機します。この場合、両方のスレッドは、他のスレッドが保持するリソースを無期限に待機します。これらのスレッドはデッドロックされていると言われています。
競合状態は、異なる命令が実行される正確な順序に応じて、2つのスレッドが否定的な(バギー)方法で対話するときに発生します。たとえば、1つのスレッドがグローバル変数を設定した場合、2番目のスレッドがそのグローバル変数を読み取って変更し、最初のスレッドが変数を読み取ると、変数が予期せず変更されたために最初のスレッドにバグが発生する可能性があります。
デッドロック:
レース/レース条件:
コーディングでは、競合状態とデッドロック状態の両方を回避する必要があります。
「競合状態」ではなく「競合状態」を意味すると仮定します(その言葉を聞いたことがあります...)
基本的に、デッドロックは、スレッドAがリソースYのロックを保持しながらリソースXを待機し、スレッドBがリソースXのロックを保持しながらリソースYを待機している状態です。ロック。
この問題の解決策は、(通常)すべてのスレッドで同じ順序ですべてのリソースを確実にロックすることです。たとえば、リソースXを常にロックする場合beforeリソースYの場合、この例ではデッドロックが発生することはありません。
競合状態とは、特定の順序で発生するイベントの特定のシーケンスに依存しているものの、別のスレッドが同時に実行されている場合は混乱する可能性があります。たとえば、リンクリストに新しいノードを挿入するには、リストヘッドを変更する必要があります。通常は次のようになります。
newNode->next = listHead;
listHead = newNode;
しかし、2つのスレッドが同時にそれを行う場合、次のように実行される状況になる可能性があります。
Thread A Thread B
newNode1->next = listHead
newNode2->next = listHead
listHead = newNode2
listHead = newNode1
これが発生した場合、スレッドAがリストを上書きしたため、スレッドBによるリストの変更は失われます。状況によってはさらに悪化することもありますが、それが基本です。
この問題の解決策は通常、適切なロックメカニズムを含めることです(たとえば、リンクリストを変更するたびにロックを解除して、一度に1つのスレッドのみが変更するようにします)。