スレッドの「デッドロック」を簡単な言葉で説明するのに苦労しているので、助けてください。「デッドロック」の最良の例 (Java など) とは? ただし、詳細に深く入り込むことはありません。私はそれが2つの反対のことを尋ねるようなものであることを知っていますが、それでも. 並行プログラミングのトレーニング経験があれば、それは素晴らしいことです。
15 に答える
ジャックとジルはたまたま同時にサンドイッチを作りたがっていました。どちらもパンが必要なので、パンとナイフを取りに行きます。
ジャックが先にナイフを手に入れ、ジルが先にパンを手に入れる。ジャックは一斤のパンを、ジルはナイフを見つけようとしますが、どちらもタスクを完了するために必要なものはすでに使用されていることに気づきます。必要なものが使用されなくなるまで待つことにした場合、両者は永遠にお互いを待ちます。デッドロック。
最も簡単な方法は、2 つの異なるスレッドが異なる順序で 2 つのロックを取得しようとすることです。
thread 1:
lock(a)
lock(b)
thread2:
lock(b)
lock(a)
スレッド 1 がロック A を取得してからスリープ状態になるとします。スレッド 2 はロック B を取得してから、ロック A を取得しようとします。ロック A が取得されているため、スレッド 2 は、スレッド A のロックが解除されるまでスリープ状態になります。ここで、スレッド 1 が復帰し、ロック B を取得しようとしてスリープ状態になります。
この場合、それを防ぐ方法がいくつかあります。
- スレッドが 2 つのロックを同時に保持する必要はありません。
- 2 つのロックを同時に保持する必要がある場合は、常に同じ順序で取得する必要があります (上の例では、ロック B を要求する前にロック A を要求するようにスレッド 2 を変更する必要があります)。
コンピュータとはまったく関係のない言葉で説明したいと思います。それがアイデアを理解するための最良の方法であることが多いからです。
5歳の息子と3歳の娘がいます。どちらも同じ塗り絵をしたいと思っています。
息子が本をつかみながら、娘は鉛筆をつかみます。どちらも、もう一方を手に入れるまで、持っているものを手放しません。
それはデッドロックです。これ以上簡単なことはありません。
あなたのプロセス (または子プロセス) はお互いを待って立ち往生し、他の上位プロセス (Dad など) が入ってきてデッドロックを解消するまで、無期限に待機し続けます。
少なくとも子供の場合は、(場合によっては) そのうちの 1 人に理由を見てもらい、ロックを放棄することができます。プロセスはそのリソースを待機する以外は何もしていないため、これは通常コンピュータでは不可能です (ただし、子供もこの状態になることがあります)。
1 つのルールに従うと、デッドロックが発生しないことが保証されます。
- すべての実行スレッドが同じ順序でリソースを割り当てられるようにします。
いくつかの追加ルールに従うことで、スレッド同士の速度が低下する可能性が低くなりますが、上記のルールは他のすべてのルールよりも優先されることに注意してください。
- 必要なときにだけリソースを割り当てます。
- 使い終わったらすぐに解放してください。
Thrd 1 --- Lock A - atmpt lock on B -
\ / \
\ / \
\ / \
--- Lock A / --- wait for lock on B
Thrd 2--- Lock B - atmpt lock on A -
\ / \
\ / \
\ / \
--- Lock B / --- wait for lock on A
スレッド 1 が実行され、A がロックされ、何らかの処理が行われ、B をロックするスレッド 2 によって中断され、B をロックしようとするスレッド 1 によって中断されますが、スレッド 2 が B をロックしているため、スレッド 1 は待機し、中断されます。スレッド 2 は A をロックしようとしますが、スレッド 1 は A をロックしているため、スレッド 2 は待機する必要があります。
両方のスレッドは、他のスレッドがロックを取得しようとしているリソースのロックを解放するのを待っています...
デッドロック
デッドロックを示すもう 1 つの良い方法は、SQL Server を使用することです。
さまざまな分離レベルのトランザクションを使用して、あるトランザクションが別のトランザクションによってロックされているテーブルを無期限に待機する方法を示すことができます。
ここでのプラスは、SQL Management Studio でそれを実証できることです。私は過去にこれを使用して、「SQL Server の概要」レベルのトレーニング コースを教えながら、人々にデッドロックを説明しました。
ほとんどの参加者は理論に問題を抱えていますが、(通常は) 実際にそれを見ればすべてが明らかになります。
つまり、トランザクション A (完了していない) は、明示的なテーブル ロックを取得します。2 番目のトランザクション B は、トランザクション A によってロックされたテーブルからの読み取りを試みます。トランザクション A がコミットされるかロールバックされるまで、トランザクション B はデッドロックされます。
これは、トランザクションを作成する 2 つの別個のスレッドを作成することで、コードでかなり簡単に説明できます。それが役に立てば幸い。
通常、並行プログラミングのクラスでは、デッドロックについて例を挙げて説明しています。食事の哲学者の問題が良い例になると思います。この例を Java で作成し、2 人の哲学者が左のフォークを保持し、右のフォークを待っているときにデッドロックが発生することを説明できます。(またはその逆)。
Java で実装されたこの例を使用して、並行プログラミングから多くの概念を学びました。
グッファの説明は良いです。
デッドロックを回避するために私が見つけた最善の方法は、自分専用のリソースのみをロックし、排他制御できないものを呼び出す前にロックを解放することです。
唯一の問題は、一貫性を維持するためにロックを使用することから、補正アクションを使用することに移行する必要があることですが、いずれにせよ、長期的には問題が発生する可能性は低いでしょう。
この記事は、この問題について読むのに適しています。
(やや簡略化) ボルトにナットをねじ込んでいる人が 2 人います。
手順 (どちらも同じ) は次のとおりです。
- ナットまたはボルトを拾う
- ボルトまたはナットを拾います (まだ持っていない方)
- ナットをボルトにねじ込みます
- 完成したアセンブリを「完成」パイルに置きます。
- ナットとボルトが残っている場合は、手順 1 に進みます
では、ナットとボルトだけが残っているとどうなるでしょうか? 最初の人はナットを拾い、2 人目はボルトをつかみます。ここまでは順調ですが、それぞれが必要なリソースを持っており、行き詰まっています。
特別な指示がなければ、彼らは永遠に膠着状態に陥ります。
または、このビデオを見せることもできます
デッドロックとは、2 つのスレッドが互いに待機し、どちらも先に進むまで先に進めず、両方ともスタックすることです。
デッドロックには少なくとも 2 つのロックが必要であり、両方のスレッドに、ロックを取得し、ロックが解放されるのを待機するコードが含まれている必要があります。
スレッド 1 はロック A を持っており、ロック B を必要としているため、ロック B が解放されるのを待ちます。
スレッド 2 にはロック B があり、ロック A が必要なため、ロック A が解放されるのを待ちます。
これでデッドロックが発生しました。両方のスレッドがロックを待っているため、どちらも実行されていないため、どちらも他方が待機しているロックを解放できません。
デッドロックは、2 つの異なるスレッドがそれらを使用するためにロックする必要がある 2 つの異なるリソースがある場合に発生します。スレッドは逆の順序でそれらをロックするため、スレッドの 1 つが元に戻るまで実行を続行できなくなります。
ウィキペディアには、デッドロックの良い実例がいくつかあります。
ワーカーが別のワーカーによってブロックされると、ロック チェーンが発生します。A は B のために続行できません。チェーンは長くなる可能性があります。A は B によってブロックされ、B は C によってブロックされ、C は D によってブロックされます。
デッドロックとは、ロック チェーンがループを形成することです。A は B によってブロックされ、B は C によってブロックされ、C は A によってブロックされ、チェーンがループを形成していたため、進行は不可能です。
デッドロックを防ぐ一般的な方法は、ロック階層を使用することです。すべてのワーカーが常に同じ順序でロックを取得する場合、デッドロックは発生しません。これは、ランク X のロックを保持し、ランク Y のリソースを待機するワーカー間で各ブロックが発生するためです。ここで、 X > Y 常に。この場合、ループを閉じるには少なくとも 1 つのワーカーが階層に反する必要があるため、ループは形成されません。少なくとも、理論はどうなるか。実際には、現実的な階層を考え出すのは非常に困難です (いいえ、リソースのアドレスは機能しません)。
デッドロックを回避できない場合 (データベース システムなど)、解決策は、ループを検索してデッドロック チェーンをチェックし、参加者の 1 つを強制終了してループを解放する専用スレッドを用意することです。
食事の哲学者 - テーブルに 4 人が座っていて、箸が 4 本あります。食べるには箸が2本必要です。各哲学者が次のように食べようとしていると想像してください。
- 左の箸を取ります。
- 右の箸を取ります。
- 食べる。
- 右の箸を戻す。
- 左の箸を戻す。
誰もがステップ 1 を実行します。ステップ 2 は不可能です。なぜなら、各人は自分の右にいる人が左をドロップするのを待っているからです。これはデッドロックです。交代で食べれば全員が食べられるのに、全員が飢えてしまう。
サンプル1:
私は決して約束をしないと約束した
サンプル 2:
ランプの魔神と話す:私の願いはあなたが決して願いを叶えないことです
サンプル3:
採用担当者: デッドロックについて説明していただければ採用します。
候補者: 私を雇ってくれたら、デッドロックとは何かを説明します