誰かがスレッド競合とは何かを簡単に説明できますか?
私はそれをグーグルで調べました、しかし簡単な説明を見つけることができないようです。
誰かがスレッド競合とは何かを簡単に説明できますか?
私はそれをグーグルで調べました、しかし簡単な説明を見つけることができないようです。
回答:
基本的にスレッドの競合とは、あるスレッドが別のスレッドによって現在保持されているロック/オブジェクトを待機している状態です。したがって、この待機中のスレッドは、他のスレッドがその特定のオブジェクトのロックを解除するまで、そのオブジェクトを使用できません。
いくつかの回答はロックの競合に焦点を当てているようですが、競合が発生する可能性があるのはロックだけではありません。競合とは、2つのスレッドが同じリソースまたは関連するリソースにアクセスしようとしたときに、競合するスレッドの少なくとも1つが他のスレッドが実行されていなかった場合よりも実行速度が遅くなることです。
競合の最も明白な例はロックです。スレッドAにロックがあり、スレッドBが同じロックを取得したい場合、スレッドBはスレッドAがロックを解放するまで待機する必要があります。
これはプラットフォーム固有ですが、他のスレッドがロックを解放するのを待つ必要がない場合でも、スレッドの速度が低下する可能性があります。これは、ロックによってある種のデータが保護され、データ自体も競合することが多いためです。
たとえば、ロックを取得し、オブジェクトを変更してから、ロックを解放して他のことを行うスレッドを考えてみます。2つのスレッドがこれを行っている場合、たとえロックを争うことがなくても、1つのスレッドしか実行していない場合よりも、スレッドの実行速度が大幅に遅くなる可能性があります。
どうして?各スレッドが最新のx86 CPU上の独自のコアで実行されており、コアがL2キャッシュを共有していないとします。スレッドが1つだけの場合、オブジェクトはほとんどの場合L2キャッシュに残る可能性があります。両方のスレッドが実行されている場合、一方のスレッドがオブジェクトを変更するたびに、もう一方のCPUがキャッシュラインを無効にしたため、もう一方のスレッドはL2キャッシュにデータがないことを検出します。たとえば、Pentium Dでは、これによりコードがL2キャッシュ速度よりもはるかに遅いFSB速度で実行されます。
ロック自体が競合しない場合でも競合が発生する可能性があるため、ロックがない場合にも競合が発生する可能性があります。たとえば、CPUが32ビット変数のアトミックインクリメントをサポートしているとします。1つのスレッドが変数をインクリメントおよびデクリメントし続けると、その変数は多くの場合、キャッシュ内でホットになります。2つのスレッドがそれを行うと、それらのキャッシュはその変数を保持するメモリの所有権をめぐって競合し、キャッシュコヒーレンシプロトコルがキャッシュラインの各コアの所有権を保護するように動作するため、多くのアクセスが遅くなります。
皮肉なことに、ロックは通常競合を減らします。どうして?ロックがないと、2つのスレッドが同じオブジェクトまたはコレクションを操作し、多くの競合を引き起こす可能性があるためです(たとえば、ロックのないキューがあります)。ロックは競合するスレッドのスケジュールを解除する傾向があり、競合しないスレッドを代わりに実行できます。スレッドAがロックを保持し、スレッドBが同じロックを必要とする場合、実装は代わりにスレッドCを実行できます。スレッドCがそのロックを必要としない場合は、しばらくの間、スレッドAとBの間の将来の競合を回避できます。(もちろん、これは実行可能な他のスレッドがあることを前提としています。システム全体が有益な進歩を遂げることができる唯一の方法が競合するスレッドを実行することである場合、それは役に立ちません。)
ここから:
競合は、スレッドがすぐに利用できないリソースを待っているときに発生します。コードの実行は遅くなりますが、時間の経過とともに解消される場合があります。
デッドロックは、スレッドが2番目のスレッドがロックしたリソースを待機していて、2番目のスレッドが最初のスレッドがロックしたリソースを待機しているときに発生します。3つ以上のスレッドがデッドロックに関与する可能性があります。デッドロックが解決することはありません。多くの場合、アプリケーション全体、またはデッドロックが発生している部分が停止します。
質問の背景にはOPからの説明があるはずだと思います-2つの回答が考えられます(このリストに追加があると確信しています)。
スレッドの競合の一般的な「概念」と、それがアプリケーションでどのように表示されるかについて言及している場合は、上記の@DavidSchwartzの詳細な回答に従います。
「.NET CLRロックおよびスレッド:競合の総数」パフォーマンスカウンターもあります。このカウンターのPerfMonの説明から取ったように、次のように定義されます。
このカウンターは、CLRのスレッドが管理されたロックの取得に失敗した合計回数を表示します。管理ロックはさまざまな方法で取得できます。C#の "lock"ステートメント、System.Monitor.Enterの呼び出し、またはMethodImplOptions.Synchronizedカスタム属性の使用。
...他のOSやアプリケーションフレームワークについては、他の人もきっと確信しています。
別の言葉は並行性かもしれません。それは単に、2つ以上のスレッドが同じリソースを使用しようとするという考えです。
次のシナリオを想像してみてください。あなたは明日の最終試験の準備をしていて、少しお腹が空いています。それで、あなたはあなたの弟に10ドルを与えて、あなたにピザを買うように彼に頼みます。この場合、あなたはメインスレッドであり、あなたの兄弟は子スレッドです。注文が与えられると、あなたと兄弟の両方が同時に仕事をします(つまり、ピザの勉強と購入)。ここで、考慮すべき2つのケースがあります。最初に、あなたの兄弟はあなたのピザを持ち帰り、あなたが勉強している間に終了します。この場合、勉強をやめてピザを楽しむことができます。第2に、ピザが利用可能になる前に、勉強を早く終えて、寝る(つまり、今日の割り当てられた仕事-明日の最終試験の勉強-が完了する)。もちろん、眠ることはできません。そうでなければ、ピザを食べる機会がありません。
例のように、2つのケースは競争の意味を与えます。
ロックの競合は、スレッドが他のスレッドによってすでに取得されているオブジェクトへのロックを取得しようとしたときに発生します*。オブジェクトが解放されるまで、スレッドはブロックされます(つまり、スレッドは待機状態です)。場合によっては、これがいわゆるシリアル実行につながり、アプリケーションに悪影響を与えることがあります。